diff --git a/class/achievements/Achievement$Status.class b/class/achievements/Achievement$Status.class new file mode 100644 index 0000000000000000000000000000000000000000..d3f3ccf61dced4e6181aa3a070314dc554e648cb Binary files /dev/null and b/class/achievements/Achievement$Status.class differ diff --git a/class/achievements/Achievement.class b/class/achievements/Achievement.class new file mode 100644 index 0000000000000000000000000000000000000000..f802356414526596b846906cbbaeddec73c404a7 Binary files /dev/null and b/class/achievements/Achievement.class differ diff --git a/class/achievements/AchievementCell.class b/class/achievements/AchievementCell.class new file mode 100644 index 0000000000000000000000000000000000000000..02361668f9e9f2748dbaf121cccedab3ec4e525f Binary files /dev/null and b/class/achievements/AchievementCell.class differ diff --git a/class/achievements/AchievementHandler$1.class b/class/achievements/AchievementHandler$1.class new file mode 100644 index 0000000000000000000000000000000000000000..d5fb6e120287eebbc988fa96007ead6e66df18d4 Binary files /dev/null and b/class/achievements/AchievementHandler$1.class differ diff --git a/class/achievements/AchievementHandler.class b/class/achievements/AchievementHandler.class new file mode 100644 index 0000000000000000000000000000000000000000..10a58e0e237954c7c6d2c85f01171efa37c4ec94 Binary files /dev/null and b/class/achievements/AchievementHandler.class differ diff --git a/class/achievements/NotIncrementalAchievementException.class b/class/achievements/NotIncrementalAchievementException.class new file mode 100644 index 0000000000000000000000000000000000000000..3e64234d1478e12d98df36180eeee3103b082e1f Binary files /dev/null and b/class/achievements/NotIncrementalAchievementException.class differ diff --git a/class/application/Controller$1.class b/class/application/Controller$1.class index 8d76c2efc9ade0aefbee720d3d7a288e82109a3f..0bb983de96e9ee9eb94f11793205ab0acf3e8fcc 100644 Binary files a/class/application/Controller$1.class and b/class/application/Controller$1.class differ diff --git a/class/application/Controller$2.class b/class/application/Controller$2.class index f23206c0f1874cbb90c2b098526ab5724da5e690..7c153ebe49a16981927495bab22b0f5e44ba817b 100644 Binary files a/class/application/Controller$2.class and b/class/application/Controller$2.class differ diff --git a/class/application/Controller$3.class b/class/application/Controller$3.class index c7ec3c1441a78120e55da1b9b0365376bf8f3f38..e995ad78058dc0075e92f4d019596ca6a852346a 100644 Binary files a/class/application/Controller$3.class and b/class/application/Controller$3.class differ diff --git a/class/application/Controller$4.class b/class/application/Controller$4.class index 3f5dcc86d4bd47f4664901e98cfe9d12795ec3f3..f760bfb28e3b34815d094f58c0523a6ad1ba6581 100644 Binary files a/class/application/Controller$4.class and b/class/application/Controller$4.class differ diff --git a/class/application/Controller$5.class b/class/application/Controller$5.class index 2c1427ca3ee321dcb9ba14da25637f24c640602d..8c983bf756dfbf3ecee53c89b43175ddf93df918 100644 Binary files a/class/application/Controller$5.class and b/class/application/Controller$5.class differ diff --git a/class/application/Controller$6.class b/class/application/Controller$6.class index d6822e7690c9a11b990721759e7517c6e1985df7..3a672481e1cce7d47bc4ee8256a826ea6204c4c0 100644 Binary files a/class/application/Controller$6.class and b/class/application/Controller$6.class differ diff --git a/class/application/Controller$7.class b/class/application/Controller$7.class index 4b967274d7006d93eb6dd2090b381b98e88997ee..cc0f8c90412e1aaf8fcfce7d2945ec490701e31a 100644 Binary files a/class/application/Controller$7.class and b/class/application/Controller$7.class differ diff --git a/class/application/Controller$8.class b/class/application/Controller$8.class index 7c854109def74bd3216e501aab24ff3d26698064..f615460930a778653bed115a4347356b5ae0122b 100644 Binary files a/class/application/Controller$8.class and b/class/application/Controller$8.class differ diff --git a/class/application/Controller$9.class b/class/application/Controller$9.class new file mode 100644 index 0000000000000000000000000000000000000000..3870d35bf8628bebe3661cbdf52b81c168ee9eca Binary files /dev/null and b/class/application/Controller$9.class differ diff --git a/class/application/Controller.class b/class/application/Controller.class index 2bf6ce689767dff9b6de1d6889fc0accf73f5b8f..9fccc2f1e2978d55b8bde630a13a0c98944383f5 100644 Binary files a/class/application/Controller.class and b/class/application/Controller.class differ diff --git a/class/application/MainGUI.fxml b/class/application/MainGUI.fxml index 8321e0c587824f815495bcd971eb0aebacfd8a95..03681dfcc0769858ea129bf7ec76c0b6f2952a09 100644 --- a/class/application/MainGUI.fxml +++ b/class/application/MainGUI.fxml @@ -79,6 +79,7 @@ <Menu fx:id="menu1" mnemonicParsing="false" text="Menü"> <items> <MenuItem fx:id="menuItem2" mnemonicParsing="false" onAction="#openSettings" text="Einstellungen" /> + <MenuItem fx:id="menuItem1" mnemonicParsing="false" onAction="#buttonAchievements" text="Achievements" /> <MenuItem fx:id="menuItem3" mnemonicParsing="false" onAction="#about" text="Über" /> </items> </Menu> @@ -89,7 +90,7 @@ <Image url="@../images/icon.png" /> </image> </ImageView> - <Label fx:id="labelLogo" layoutX="274.0" layoutY="385.0" text="Welcome to UNO!"> + <Label fx:id="labelLogo" layoutX="244.0" layoutY="385.0" text="Willkommen bei UNO!"> <font> <Font name="System Bold" size="28.0" /> </font> diff --git a/class/application/PathSettings.class b/class/application/PathSettings.class deleted file mode 100644 index 3325c7acc9f96544b9d89e46a0522c912ec15c5c..0000000000000000000000000000000000000000 Binary files a/class/application/PathSettings.class and /dev/null differ diff --git a/class/logic/Game.class b/class/logic/Game.class index 8301270ed69f692be18fa4a00d284ee9dc2dc451..8991b1a428eac2e6200d00d72e65dd6ad26dc7cd 100644 Binary files a/class/logic/Game.class and b/class/logic/Game.class differ diff --git a/class/logic/Player.class b/class/logic/Player.class index 5f2532c232e602fabd6155b0732015f0e3129205..cf2613e5e91c87582b73621ed5a7cf188da2fb0e 100644 Binary files a/class/logic/Player.class and b/class/logic/Player.class differ diff --git a/class/sounds/Sound.class b/class/sounds/Sound.class new file mode 100644 index 0000000000000000000000000000000000000000..c0206a7ba1ff7a26f067397a6cdd3ff98a8073ab Binary files /dev/null and b/class/sounds/Sound.class differ diff --git a/class/sounds/unlocked.mp3 b/class/sounds/unlocked.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..fc3562c1d3c1a4cb3d58a2cffb2ff444197972d1 Binary files /dev/null and b/class/sounds/unlocked.mp3 differ diff --git a/src/achievements/Achievement.java b/src/achievements/Achievement.java new file mode 100644 index 0000000000000000000000000000000000000000..702383d55814f045198cd7b773556f1e8b67b3f9 --- /dev/null +++ b/src/achievements/Achievement.java @@ -0,0 +1,198 @@ +package achievements; + +import java.io.Serializable; +/** + * Repr�sentiert ein Achievement + * @author Robert + * + */ +@SuppressWarnings("serial") +public class Achievement implements Serializable +{ + private String name; + private String description; + private String iconLocked; + private String iconUnlocked; + private Status status; + private boolean incremental; + private int startValue; + private int endValue; + private int currentValue; + + /** + * Enum f�r den Status des Achievements + * @author Robert + */ + public enum Status + { + //Hidden = Locked --> aber nur Name und Platzhalter-Icon wird angezeigt + HIDDEN, LOCKED, UNLOCKED + } + + /** + * Konstruktor f�r ein normales Achievement + * @param name String - Nam + * @param description String - Beschreibungstext + * @param iconLocked String - Pfad zum Icon solange das Achievement noch nicht freigeschaltet wurde + * @param iconUnlocked String - Pfad zum Icon, wenn das Achievement freigeschaltet wurde + * @param status Status - Status + */ + public Achievement(String name, String description, String iconLocked, String iconUnlocked, Status status) + { + this.name = name; + this.description = description; + this.iconLocked = iconLocked; + this.iconUnlocked = iconUnlocked; + this.status = status; + this.incremental = false; + } + + /** + * Konstruktor f�r ein inkrementierbares Achievement + * @param name String - Nam + * @param description String - Beschreibungstext + * @param iconLocked String - Pfad zum Icon solange das Achievement noch nicht freigeschaltet wurde + * @param iconUnlocked String - Pfad zum Icon, wenn das Achievement freigeschaltet wurde + * @param status Status - Status + * @param startValue int - Startwert + * @param endValue int - Endwert (Wenn erreicht oder �berschritten wird Achievement freigeschaltet) + * @param currentValue - aktuller Wert + */ + public Achievement(String name, String description, String iconLocked, String iconUnlocked, Status status, int startValue, int endValue, int currentValue) + { + this.name = name; + this.description = description; + this.iconLocked = iconLocked; + this.iconUnlocked = iconUnlocked; + this.status = status; + this.incremental = true; + this.startValue = startValue; + this.endValue = endValue; + this.currentValue = currentValue; + } + + /** + * Gibt den Namen zur�ck + * @return String - Name + */ + public String getName() + { + return name; + } + + /** + * Gibt den Beschreibungstext zur�ck + * @return String - Beschreibung + */ + public String getDescription() + { + return description; + } + + /** + * Gibt den Pfad zum Icon f�r das nicht freigeschaltete Achievement zur�ck + * @return String - Pfad zu "iconLocked" + */ + public String getIconLocked() + { + return iconLocked; + } + + /** + * Gibt den Pfad zum Icon f�r das freigeschaltete Achievement zur�ck + * @return String - Pfad zu "iconUnlocked" + */ + public String getIconUnlocked() + { + return iconUnlocked; + } + + /** + * Gibt den Status zur�ck + * @return Status - Status + */ + public Status getStatus() + { + return status; + } + + /** + * gibt zur�ck, ob das Achievemnt ein inkrementierbares Achievement ist + * @return boolean - ist inkrementierbar + */ + public boolean isIncremental() + { + return incremental; + } + + /** + * gibt den Startwert zur�ck + * @return int - Startwert + */ + public int getStartValue() + { + return startValue; + } + + /** + * gibt den Endwert zur�ck + * @return int - Endwert + */ + public int getEndValue() + { + return endValue; + } + + /** + * gibt den aktuellen Wert zur�ck + * @return int - aktueller Wert + */ + public int getCurrentValue() + { + return currentValue; + } + + /** + * setzt den aktuellen Wert + * @param value int - aktueller Wert + */ + public void setCurrentValue(int value) + { + this.currentValue = value; + } + + /** + * erh�ht den aktuellen Wert + * @param value int - Einheiten, um die der aktuelle Wert erh�ht werden soll + */ + public void incrementCurrentValue(int value) + { + if(!status.equals(Status.UNLOCKED)) + { + if(this.currentValue < endValue) + { + this.currentValue += value; + } + } + } + + /** + * setzt den Status + * @param status Status - Status + */ + public void setStatus(Status status) + { + this.status = status; + } + + /** + * toString()-Implementierung (Ausgabe f�r Debugging) + * @return String - Ausgabe + */ + @Override + public String toString() + { + return "name: " + name + ", description: " + description + ", iconLocked: " + iconLocked + ", iconUnlocked : " + iconUnlocked + ", status: " + status + ", incremental: " + incremental + ", startValue: " + startValue + ", endValue: " + + endValue + ", currentValue:" + currentValue + "]"; + } +} \ No newline at end of file diff --git a/src/achievements/AchievementCell.java b/src/achievements/AchievementCell.java new file mode 100644 index 0000000000000000000000000000000000000000..d5637f7b06e5cd14012f10625f23fc76611d1635 --- /dev/null +++ b/src/achievements/AchievementCell.java @@ -0,0 +1,227 @@ +package achievements; + +import java.io.File; + +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ProgressBar; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import achievements.Achievement.Status; + +/** + * eigene ListCell, um die Achievements darzustellen + * @author Robert + * + */ +public class AchievementCell extends ListCell<Achievement> +{ + private int iconSize = 50; + private String colorLocked = "#C6C6C6"; + private String colorUnlocked = "#FFFFFF"; + private int anchorPanePadding = 15; + private int anchorPaneBackgroundRadius = 10; + + @Override + protected void updateItem(Achievement item, boolean empty) + { + super.updateItem(item, empty); + + if(!empty) + { + AnchorPane anchorPaneAchievement = new AnchorPane(); + + HBox hbox = new HBox(); + VBox vbox = new VBox(); + + if(item.getStatus().equals(Status.HIDDEN)) + { + //f�r versteckte Erfolge wird das Standard Platzhaltericon verwendet + Image image = new Image("notification/trophyLocked.png"); + + ImageView view = new ImageView(image); + view.setFitWidth(iconSize); + view.setFitHeight(iconSize); + + hbox.getChildren().add(view); + + Label labelName = new Label(item.getName()); + labelName.setStyle("-fx-font-weight: bold; -fx-font-size: 17px;"); + labelName.prefWidthProperty().bind(vbox.widthProperty()); + + Label labelDescription = new Label("???"); + labelDescription.setStyle("-fx-font-size: 16px;"); + labelDescription.prefWidthProperty().bind(vbox.widthProperty()); + + vbox.getChildren().add(labelName); + vbox.getChildren().add(labelDescription); + vbox.setAlignment(Pos.CENTER); + + anchorPaneAchievement.setStyle("-fx-background-radius: " + anchorPaneBackgroundRadius + "; -fx-background-color: " + colorLocked + ";"); + } + else if(item.getStatus().equals(Status.LOCKED)) + { + Image image; + + if(item.getIconLocked() != null) + { + File file = new File(item.getIconLocked()); + if(file.exists()) + { + image = new Image(file.toURI().toString()); + } + else + { + //falls der Pfad nicht existiert oder ung�ltig ist wird das Standardicon genommen + image = new Image("notification/trophyLocked.png"); + } + } + else + { + //falls der Pfad nicht existiert oder ung�ltig ist wird das Standardicon genommen + image = new Image("notification/trophyLocked.png"); + } + + ImageView view = new ImageView(image); + view.setFitWidth(iconSize); + view.setFitHeight(iconSize); + + hbox.getChildren().add(view); + + Label labelName = new Label(item.getName()); + labelName.setStyle("-fx-font-weight: bold; -fx-font-size: 17px;"); + labelName.prefWidthProperty().bind(vbox.widthProperty()); + + Label labelDescription = new Label(item.getDescription()); + labelDescription.setStyle("-fx-font-size: 16px;"); + labelDescription.prefWidthProperty().bind(vbox.widthProperty()); + + vbox.getChildren().add(labelName); + vbox.getChildren().add(labelDescription); + + if(item.isIncremental()) + { + ProgressBar progressbar = new ProgressBar(); + progressbar.setProgress(1.0 * item.getCurrentValue() / item.getEndValue()); + progressbar.prefWidthProperty().bind(vbox.widthProperty().multiply(0.65)); + progressbar.setStyle("-fx-accent: #888888;"); + + Label labelProgress = new Label(item.getCurrentValue() + "/" + item.getEndValue()); + labelProgress.setStyle("-fx-font-size: 15px;"); + + HBox progress = new HBox(); + progress.getChildren().add(progressbar); + progress.getChildren().add(labelProgress); + HBox.setHgrow(progressbar, Priority.ALWAYS); + HBox.setMargin(labelProgress, new Insets(0, 0, 0, 10)); + progress.setAlignment(Pos.CENTER_LEFT); + progress.setMinWidth(300); + + vbox.getChildren().add(progress); + + progress.prefWidthProperty().bind(vbox.widthProperty()); + VBox.setMargin(progress, new Insets(3, 0, 0, 0)); + } + else + { + vbox.setAlignment(Pos.CENTER); + } + anchorPaneAchievement.setStyle("-fx-background-radius: " + anchorPaneBackgroundRadius + "; -fx-background-color:" + colorLocked + ";"); + } + else + { + Image image; + if(item.getIconUnlocked() != null) + { + File file = new File(item.getIconUnlocked()); + if(file.exists()) + { + image = new Image(file.toURI().toString()); + } + else + { + //falls der Pfad nicht existiert oder ung�ltig ist wird das Standardicon genommen + image = new Image("notification/trophyUnlocked.png"); + } + } + else + { + //falls der Pfad nicht existiert oder ung�ltig ist wird das Standardicon genommen + image = new Image("notification/trophyUnlocked.png"); + } + + ImageView view = new ImageView(image); + view.setFitWidth(iconSize); + view.setFitHeight(iconSize); + + hbox.getChildren().add(view); + + Label labelName = new Label(item.getName()); + labelName.setStyle("-fx-font-weight: bold; -fx-font-size: 17px;"); + labelName.prefWidthProperty().bind(vbox.widthProperty()); + + Label labelDescription = new Label(item.getDescription()); + labelDescription.setStyle("-fx-font-size: 16px;"); + labelDescription.prefWidthProperty().bind(vbox.widthProperty()); + + vbox.getChildren().add(labelName); + vbox.getChildren().add(labelDescription); + + if(item.isIncremental()) + { + ProgressBar progressbar = new ProgressBar(); + progressbar.setProgress(1.0 * item.getCurrentValue() / item.getEndValue()); + progressbar.prefWidthProperty().bind(vbox.widthProperty().multiply(0.68)); + + Label labelProgress = new Label(item.getCurrentValue() + "/" + item.getEndValue()); + labelProgress.setStyle("-fx-font-size: 15px;"); + labelProgress.setAlignment(Pos.CENTER); + + HBox progress = new HBox(); + progress.getChildren().add(progressbar); + progress.getChildren().add(labelProgress); + HBox.setHgrow(progressbar, Priority.ALWAYS); + HBox.setMargin(labelProgress, new Insets(0, 0, 0, 10)); + progress.setAlignment(Pos.CENTER_LEFT); + progress.setMinWidth(300); + + vbox.getChildren().add(progress); + + progress.prefWidthProperty().bind(vbox.widthProperty()); + VBox.setMargin(progress, new Insets(3, 0, 0, 0)); + } + else + { + vbox.setAlignment(Pos.CENTER); + } + anchorPaneAchievement.setStyle("-fx-background-radius: " + anchorPaneBackgroundRadius + "; -fx-background-color: " + colorUnlocked + ";"); + } + + hbox.getChildren().add(vbox); + HBox.setHgrow(vbox, Priority.ALWAYS); + HBox.setMargin(vbox, new Insets(0, 0, 0, 25)); + hbox.setAlignment(Pos.CENTER); + + anchorPaneAchievement.getChildren().add(hbox); + AnchorPane.setTopAnchor(hbox, 15.0); + AnchorPane.setLeftAnchor(hbox, 15.0); + AnchorPane.setRightAnchor(hbox, 15.0); + AnchorPane.setBottomAnchor(hbox, 15.0); + + vbox.setMinHeight(65); + setStyle("-fx-background-color: transparent; -fx-padding: " + anchorPanePadding + " 10px " + anchorPanePadding +" 0px"); + setGraphic(anchorPaneAchievement); + } + else + { + setStyle("-fx-background-color: transparent;"); + setGraphic(null); + } + } +} \ No newline at end of file diff --git a/src/achievements/AchievementHandler.java b/src/achievements/AchievementHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..bdea5d9a9d71144614931a5e080933ec2a120ac4 --- /dev/null +++ b/src/achievements/AchievementHandler.java @@ -0,0 +1,475 @@ +package achievements; + +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; + +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.control.ProgressBar; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import javafx.util.Callback; +import notification.Notification; +import sounds.Sound; +import achievements.Achievement.Status; + +/** + * Verwaltet die Achievements + * @author Robert + * + */ +public class AchievementHandler +{ + private ArrayList<Achievement> achievements; + private Notification notification; + private Stage owner; + private String path; + + //verschiedene Konstanten, die lediglich f�r die Erzeugung der ListView verwendet werden + private final int iconSize = 50; + private final String colorUnlocked = "#FFFFFF"; + private final int anchorPanePadding = 15; + private final int anchorPaneBackgroundRadius = 10; + + /** + * Konstruktor + * @param owner Stage - Owner + */ + public AchievementHandler(Stage owner) + { + achievements = new ArrayList<Achievement>(); + notification = new Notification(); + this.owner = owner; + } + + /** + * setzt den Pfad zum Lesen und Speichern der Achievementsdatei + * @param path + */ + public void setPath(String path) + { + this.path = path; + } + + /** + * f�gt ein Achievement zur Liste hinzu + * @param achievement + */ + public void addAchievement(Achievement achievement) + { + achievements.add(achievement); + } + + /** + * L�scht die gesamte Achievementliste + */ + public void clearAchievementsList() + { + achievements.clear(); + } + + /** + * gibt die Achievementliste zur�ck + * @return ArrayList<Achievement> - Achievements + */ + public ArrayList<Achievement> getAchievements() + { + return achievements; + } + + /** + * entfernt das Achievement an der gegebenen Position aus der Liste + * @param position int - Position, die gel�scht werden soll + */ + public void removeAchievement(int position) + { + achievements.remove(position); + } + + /** + * gibt die Anzahl aller Achievements zur�ck + * @return int - Anzahl der Achievements + */ + public int getNumberofAchievements() + { + return achievements.size(); + } + + /** + * gibt die Anzahl der freigeschalteten Achievements zur�ck + * @return int - Anzahl der freigeschalteten Achievements + */ + public int getNumberOfUnlockedAchievements() + { + int counter = 0; + for(int i = 0; i < achievements.size(); i++) + { + if(achievements.get(i).getStatus().equals(Status.UNLOCKED)) + { + counter++; + } + } + return counter; + } + + /** + * gibt die Anzahl der nicht freigeschalteten Achievements zur�ck + * @return int - Anzahl der nicht freigeschalteten Achievements + */ + public int getNumberOfLockedAchievements() + { + int counter = 0; + for(int i = 0; i < achievements.size(); i++) + { + Status status = achievements.get(i).getStatus(); + if(status.equals(Status.LOCKED) || status.equals(Status.HIDDEN)) + { + counter++; + } + } + return counter; + } + + /** + * gibt eine AnchorPane zur�ck, die eine ListView beinhaltet + * diese stellt die Achievements mit Hilfe der AchievementCell dar + * @return + */ + public AnchorPane getAchievementList() + { + AnchorPane list = new AnchorPane(); + + ListView<Achievement> listView = new ListView<>(); + listView.setFocusTraversable(false); + Label placeHolder = new Label("Keine Achievements verf�gbar"); + placeHolder.setStyle("-fx-font-size: 16px;"); + listView.setPlaceholder(placeHolder); + list.getChildren().add(listView); + listView.getItems().addAll(achievements); + listView.setFixedCellSize(105); + listView.setStyle("-fx-background-color: transparent;"); + + listView.setCellFactory(new Callback<ListView<Achievement>, ListCell<Achievement>>() + { + @Override + public ListCell<Achievement> call(ListView<Achievement> arg0) + { + return new AchievementCell(); + } + }); + + AnchorPane.setTopAnchor(listView, 0.0); + AnchorPane.setLeftAnchor(listView, 0.0); + AnchorPane.setRightAnchor(listView, 0.0); + AnchorPane.setBottomAnchor(listView, 0.0); + + return list; + } + + /** + * gibt eine AnchorPane zur�ck, die die Zusammenfassung aller Achievements anzeigt + * (Bsp.: 5/10 Achievements freigeschaltet = 50%) + * @return + */ + public AnchorPane getSummary() + { + AnchorPane summary = new AnchorPane(); + summary.setPrefHeight(50); + + HBox hbox = new HBox(); + VBox vbox = new VBox(); + + Image image = new Image("notification/summary.png"); + + ImageView view = new ImageView(image); + view.setFitWidth(iconSize); + view.setFitHeight(iconSize); + + hbox.getChildren().add(view); + + Label labelName = new Label(getNumberOfUnlockedAchievements() + " von " + getNumberofAchievements() + " Achievements freigeschaltet"); + labelName.setStyle("-fx-font-weight: bold; -fx-font-size: 17px;"); + labelName.prefWidthProperty().bind(vbox.widthProperty()); + + vbox.getChildren().add(labelName); + + ProgressBar progressbar = new ProgressBar(); + progressbar.setProgress(1.0 * getNumberOfUnlockedAchievements() / getNumberofAchievements()); + progressbar.prefWidthProperty().bind(vbox.widthProperty().multiply(0.68)); + + Label labelProgress = new Label((int)((1.0 * getNumberOfUnlockedAchievements() / getNumberofAchievements()) * 100) + " %"); + labelProgress.setStyle("-fx-font-size: 15px;"); + + HBox progress = new HBox(); + progress.getChildren().add(progressbar); + progress.getChildren().add(labelProgress); + HBox.setHgrow(progressbar, Priority.ALWAYS); + HBox.setMargin(labelProgress, new Insets(0, 0, 0, 10)); + progress.setAlignment(Pos.CENTER_LEFT); + progress.setMinWidth(300); + + vbox.getChildren().add(progress); + + progress.prefWidthProperty().bind(vbox.widthProperty()); + VBox.setMargin(progress, new Insets(10, 0, 0, 0)); + + summary.setStyle("-fx-padding:" + anchorPanePadding + "; -fx-background-radius: " + anchorPaneBackgroundRadius + "; -fx-background-color: " + colorUnlocked + ";"); + + hbox.getChildren().add(vbox); + HBox.setHgrow(vbox, Priority.ALWAYS); + HBox.setMargin(vbox, new Insets(0, 0, 0, 25)); + hbox.setAlignment(Pos.CENTER); + + summary.setMinHeight(95); + summary.getChildren().add(hbox); + AnchorPane.setTopAnchor(hbox, 0.0); + AnchorPane.setLeftAnchor(hbox, 0.0); + AnchorPane.setRightAnchor(hbox, 0.0); + AnchorPane.setBottomAnchor(hbox, 0.0); + + return summary; + } + + /** + * �berpr�ft alle inkrementierbaren Achievements, ob sie ihren Endwert erreicht bzw. �berschritten haben + * Wenn ja, wird der Status auf UNLOCKED gesetzt und eine Notification am unteren rechten Bildschrimrand ge�ffnet, + * sowie ein Sound abgespielt. + */ + public void checkAllIncrementalAchievements() + { + for(int i = 0; i < achievements.size(); i++) + { + Achievement current = achievements.get(i); + + if(current.isIncremental()) + { + if(current.getStatus() != Status.UNLOCKED) + { + if(current.getCurrentValue() >= current.getEndValue()) + { + current.setStatus(Status.UNLOCKED); + + Sound.playSound("unlocked"); + + Image image; + if(current.getIconUnlocked() != null) + { + File file = new File(current.getIconUnlocked()); + if(file.exists()) + { + image = new Image(file.toURI().toString()); + } + else + { + image = new Image("notification/trophyUnlocked.png"); + } + } + else + { + image = new Image("notification/trophyUnlocked.png"); + } + + ImageView view = new ImageView(image); + view.setFitWidth(40); + view.setFitHeight(40); + + notification.setTitle("Achievement freigeschaltet"); + notification.setDescription(current.getDescription()); + notification.setIcon(image); + notification.setOwner(owner); + if(notification.isOpen()) + { + notification.close(); + } + notification.show(); + } + } + } + } + } + + /** + * Erh�ht das angegebene Achievement um die angegebene Anzahl von Einheiten + * @param position int - Position des Achievements + * @param value - Anzahl der Einheiten um die das Achievement erh�ht werden soll + * @throws NotIncrementalAchievementException - wenn as Achievement nicht inkrementierbar ist + * @throws IndexOutOfBoundsException - falls die angegebene Position nicht im Bereich der Liste liegt + */ + public void incrementAchievement(int position, int value) throws NotIncrementalAchievementException, IndexOutOfBoundsException + { + Achievement current = achievements.get(position); + + if(current.isIncremental()) + { + current.incrementCurrentValue(value); + } + else + { + throw new NotIncrementalAchievementException(); + } + } + + /** + * schaltet das angegebene Achievement frei + * (Notification erscheint am unteren rechten Bildschrimrand und ein Sound wird abgespielt. + * @param position int - Position + */ + public void unlockAchievement(int position) + { + Achievement current = achievements.get(position); + + if(!current.isIncremental() && current.getStatus() != Status.UNLOCKED) + { + current.setStatus(Status.UNLOCKED); + + Sound.playSound("unlocked"); + + Image image; + if(current.getIconUnlocked() != null) + { + File file = new File(current.getIconUnlocked()); + if(file.exists()) + { + image = new Image(file.toURI().toString()); + } + else + { + image = new Image("notification/trophyUnlocked.png"); + } + } + else + { + image = new Image("notification/trophyUnlocked.png"); + } + + notification.setTitle("Achievement freigeschaltet!"); + notification.setDescription(current.getName()); + notification.setIcon(image); + notification.setOwner(owner); + if(notification.isOpen()) + { + notification.close(); + } + notification.show(); + } + } + + /** + * Setzt das angegebene Achievement zur�ck + * --> Status wird auf LOCKED gesetzt + * --> wenn inkrementierbar, dann wird er aktuelle Wert auf den Startwert gesetzt * + * @param position + */ + public void resetAchievement(int position) + { + Achievement current = achievements.get(position); + + if(current.isIncremental()) + { + current.setCurrentValue(current.getStartValue()); + } + + if(current.getStatus().equals(Status.UNLOCKED)) + { + current.setStatus(Status.LOCKED); + } + + achievements.set(position, current); + } + + /** + * setzt alle Achievements zur�ck + */ + public void resetAllAchievements() + { + for(int i = 0; i < achievements.size(); i++) + { + resetAchievement(i); + } + } + + /** + * speichert die Achievements in eine Datei ab + * (Speicherort wird festgelegt mit setPath()) + * @throws IllegalArgumentException - falls kein Pfad gesetzt wurde + * @throws Exception - falls beim Speichern ein Fehler auftritt + */ + public void saveAchievements() throws IllegalArgumentException, Exception + { + if(path != null) + { + FileOutputStream fout = new FileOutputStream(path); + ObjectOutputStream oos = new ObjectOutputStream(fout); + + for(int i = 0; i < achievements.size(); i++) + { + oos.writeObject(achievements.get(i)); + } + oos.close(); + } + else + { + throw new IllegalArgumentException(); + } + } + + /** + * liest die Achievements aus einer Datei ein + * (Speicherort wird festgelegt mit setPath()) + * @throws IllegalArgumentException - falls kein Pfad gesetzt wurde + * @throws Exception - falls beim Lesen ein Fehler auftritt + */ + public void loadAchievements() throws IllegalArgumentException, Exception + { + if(path != null) + { + FileInputStream fin = new FileInputStream(path); + ObjectInputStream ois = new ObjectInputStream(fin); + + achievements = new ArrayList<Achievement>(); + + while(true) + { + try + { + Achievement current = (Achievement)ois.readObject(); + achievements.add(current); + } + catch(EOFException e) + { + ois.close(); + break; + } + } + } + else + { + throw new IllegalArgumentException(); + } + } + + /** + * speichert und l�dt die Achievements + * (n�tzlich nach Ver�nderung eines Achievements w�hrend des Spiels) + * @throws IllegalArgumentException - falls kein Pfad gesetzt wurde + * @throws Exception - falls beim Lesen ein Fehler auftritt + */ + public void saveAndLoad() throws IllegalArgumentException, Exception + { + saveAchievements(); + loadAchievements(); + } +} \ No newline at end of file diff --git a/src/achievements/NotIncrementalAchievementException.java b/src/achievements/NotIncrementalAchievementException.java new file mode 100644 index 0000000000000000000000000000000000000000..104a5d43554291fc762eff6a122755c498ff7613 --- /dev/null +++ b/src/achievements/NotIncrementalAchievementException.java @@ -0,0 +1,14 @@ +package achievements; + +/** + * Exception, falls auf ein Achievement Methoden angewendet werden, + * die nur bei einem incrementalAchievement m�glich sind, das aktuelle jedoch kein incrementalAchievement ist + * @author Robert + * + */ + +@SuppressWarnings("serial") +public class NotIncrementalAchievementException extends Exception +{ + +} \ No newline at end of file diff --git a/src/application/Controller.java b/src/application/Controller.java index e3d07a56c6550e9f73c40097a9855594878f4df7..5f6c56655ce499e3c06d865d43c9543d7c338524 100644 --- a/src/application/Controller.java +++ b/src/application/Controller.java @@ -7,6 +7,9 @@ import java.util.Locale; import java.util.Random; import java.util.ResourceBundle; +import achievements.Achievement; +import achievements.AchievementHandler; +import achievements.Achievement.Status; import javafx.animation.TranslateTransition; import javafx.collections.ObservableList; import javafx.event.ActionEvent; @@ -64,6 +67,7 @@ public class Controller @FXML private Button buttonStart; @FXML private MenuBar menuBar; @FXML private Menu menu1; + @FXML private MenuItem menuItem1; @FXML private MenuItem menuItem2; @FXML private MenuItem menuItem3; @FXML private ImageView imageViewLogo; @@ -75,6 +79,8 @@ public class Controller public Color chosenWishColor; public int drawCounter; public Settings settings; + public AchievementHandler handler; + private int secretCounter; public Stage stage; public Image icon = new Image("images/icon.png"); @@ -117,7 +123,52 @@ public class Controller catch(Exception e) { e.printStackTrace(); - } + } + + handler = new AchievementHandler(stage); + handler.setPath(System.getenv("APPDATA") + "/Deadlocker/UNO/achievements.save"); + try + { + handler.loadAchievements(); + } + catch(Exception e) + { + //falls die Datei nicht existiert, wird versucht die neu zu erzeugen + createAchievements(); + try + { + handler.loadAchievements(); + } + catch(Exception ex) + { + } + } + + iconLastCard.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() + { + @Override + public void handle(MouseEvent event) + { + if(secretCounter < 5) + { + secretCounter++; + if(secretCounter == 5) + { + try + { + handler.unlockAchievement(9); + handler.saveAndLoad(); + } + catch(Exception e) + { + } + } + } + else + { + } + } + }); } public void setStage(Stage stage) @@ -272,6 +323,18 @@ public class Controller @Override public void handle(ActionEvent event) { + if(game.getChallengeCounter() > 10 ) + { + try + { + handler.unlockAchievement(5); + handler.saveAndLoad(); + } + catch(Exception e) + { + } + + } moveCardFromDeckToPlayer(game.getDeck().drawCards(game.getChallengeCounter(), game.getDeadDeck())); } }); @@ -452,6 +515,31 @@ public class Controller hideWishColor(); } Card playedCard = game.getPlayer().playCard(card); + + if(playedCard.getType().equals(CardType.DRAW_FOUR) && game.getDeadDeck().getCards().get(game.getDeadDeck().getCards().size()-1).getType().equals(CardType.DRAW_FOUR) && game.getChallengeCounter() > 0) + { + try + { + handler.unlockAchievement(6); + handler.saveAndLoad(); + } + catch(Exception e) + { + } + } + + if(playedCard.getType().equals(CardType.WILD)) + { + try + { + handler.unlockAchievement(7); + handler.saveAndLoad(); + } + catch(Exception e) + { + } + } + setPlayerDeck(game.getPlayer().getDeck()); game.playCard(playedCard, newWishColor); } @@ -1057,6 +1145,80 @@ public class Controller iconLastCard.setImage(null); } + private void createAchievements() + { + AchievementHandler handler = new AchievementHandler(stage); + handler.setPath(System.getenv("APPDATA") + "/Deadlocker/UNO/achievements.save"); + handler.addAchievement(new Achievement("Anf�nger", "Gewinne dein erstes Spiel", null, null, Status.LOCKED)); + handler.addAchievement(new Achievement("Fortgeschrittener", "Gewinne insgesamt 10 Spiele", null, null, Status.LOCKED, 0, 10, 0)); + handler.addAchievement(new Achievement("Experte", "Gewinne insgesamt 50 Spiele", null, null, Status.LOCKED, 0, 50, 0)); + + handler.addAchievement(new Achievement("Gl�cksstr�hne", "Gewinne hintereinander 3 Spiele", null, null, Status.LOCKED, 0, 3, 0)); + handler.addAchievement(new Achievement("L�uft bei dir!", "Gewinne hintereinander 5 Spiele", null, null, Status.LOCKED, 0, 5, 0)); + + handler.addAchievement(new Achievement("Arme Sau", "Du musst mehr als 10 Karten ziehen", null, null, Status.LOCKED)); + handler.addAchievement(new Achievement("Gegenangriff", "Kontere eine +4", null, null, Status.LOCKED)); + handler.addAchievement(new Achievement("Wunschkonzert", "W�nsch dir eine Farbe", null, null, Status.LOCKED)); + handler.addAchievement(new Achievement("Cheatest du?", "Besitze zwei +4 Karten gleichzeitig", null, null, Status.LOCKED)); + + handler.addAchievement(new Achievement("Unm�glich", "Klicke 5 mal auf den Ablagestapel", null, null, Status.HIDDEN)); + + try + { + handler.saveAchievements(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + @FXML + private void buttonAchievements() + { + Stage newStage = new Stage(); + newStage.setMinHeight(250); + newStage.setMinWidth(250); + + AnchorPane root = new AnchorPane(); + + try + { + handler.loadAchievements(); + } + catch(Exception e) + { + } + + AnchorPane list = handler.getAchievementList(); + AnchorPane summary = handler.getSummary(); + + root.getChildren().add(summary); + root.getChildren().add(list); + + newStage.setResizable(false); + + AnchorPane.setTopAnchor(summary, 50.0); + AnchorPane.setLeftAnchor(summary, 25.0); + AnchorPane.setRightAnchor(summary, 50.0); + + AnchorPane.setTopAnchor(list, 180.0); + AnchorPane.setLeftAnchor(list, 25.0); + AnchorPane.setRightAnchor(list, 25.0); + AnchorPane.setBottomAnchor(list, 25.0); + + root.setStyle("-fx-background-color: #3F3F3F;"); + + Scene scene = new Scene(root, 800, 600); + newStage.setScene(scene); + + newStage.setTitle("Achievements"); + newStage.initModality(Modality.APPLICATION_MODAL); + newStage.getIcons().add(new Image("/images/icon.png")); + newStage.setResizable(true); + newStage.show(); + } + public void about() { Alert alert = new Alert(AlertType.INFORMATION); diff --git a/src/application/MainGUI.fxml b/src/application/MainGUI.fxml index 8321e0c587824f815495bcd971eb0aebacfd8a95..03681dfcc0769858ea129bf7ec76c0b6f2952a09 100644 --- a/src/application/MainGUI.fxml +++ b/src/application/MainGUI.fxml @@ -79,6 +79,7 @@ <Menu fx:id="menu1" mnemonicParsing="false" text="Menü"> <items> <MenuItem fx:id="menuItem2" mnemonicParsing="false" onAction="#openSettings" text="Einstellungen" /> + <MenuItem fx:id="menuItem1" mnemonicParsing="false" onAction="#buttonAchievements" text="Achievements" /> <MenuItem fx:id="menuItem3" mnemonicParsing="false" onAction="#about" text="Über" /> </items> </Menu> @@ -89,7 +90,7 @@ <Image url="@../images/icon.png" /> </image> </ImageView> - <Label fx:id="labelLogo" layoutX="274.0" layoutY="385.0" text="Welcome to UNO!"> + <Label fx:id="labelLogo" layoutX="244.0" layoutY="385.0" text="Willkommen bei UNO!"> <font> <Font name="System Bold" size="28.0" /> </font> diff --git a/src/application/PathSettings.java b/src/application/PathSettings.java deleted file mode 100644 index 57b06aa29a43550e13c955fbc787a940a031f50d..0000000000000000000000000000000000000000 --- a/src/application/PathSettings.java +++ /dev/null @@ -1,66 +0,0 @@ -package application; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.ArrayList; - -import tools.PathUtils; - -public class PathSettings implements Serializable -{ - private static final long serialVersionUID = 1L; - private String pathLogfile; - private ArrayList<String> folders; - - public PathSettings() - { - pathLogfile = ""; - folders = new ArrayList<String>(); - PathUtils.checkFolder(new File(System.getenv("APPDATA") + "/Deadlocker/PlayCount/")); - } - - public void save() throws Exception - { - FileOutputStream fileOut = new FileOutputStream(System.getenv("APPDATA") + "/Deadlocker/PlayCount/paths.config"); - ObjectOutputStream out = new ObjectOutputStream(fileOut); - out.writeObject(this); - out.close(); - fileOut.close(); - } - - public void load() throws Exception - { - FileInputStream fileIn = new FileInputStream(System.getenv("APPDATA") + "/Deadlocker/PlayCount/paths.config"); - ObjectInputStream in = new ObjectInputStream(fileIn); - PathSettings loaded = (PathSettings) in.readObject(); - in.close(); - fileIn.close(); - - this.pathLogfile = loaded.getPathLogfile(); - this.folders = loaded.getFolders(); - } - - public String getPathLogfile() - { - return pathLogfile; - } - - public ArrayList<String> getFolders() - { - return folders; - } - - public void setPathLogfile(String pathLogfile) - { - this.pathLogfile = pathLogfile; - } - - public void setFolders(ArrayList<String> folders) - { - this.folders = folders; - } -} \ No newline at end of file diff --git a/src/logic/Game.java b/src/logic/Game.java index 461fed5a0aa93ac060853ca2516be4b8a9660ace..54363f2fd8826aea5477dbdab932f0b92996e207 100644 --- a/src/logic/Game.java +++ b/src/logic/Game.java @@ -6,6 +6,7 @@ import java.util.Random; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.stage.Stage; +import achievements.Achievement.Status; import application.Controller; public class Game @@ -75,9 +76,9 @@ public class Game showingInfo = false; player.initialize(); - + player.drawCards(deck.drawCards(numberOfStartingCards, deadDeck)); - + for(AI currentAI : ais) { currentAI.initialize(); @@ -256,6 +257,8 @@ public class Game if(currentPlayer == 1) { + player.win(); + Alert alert = new Alert(AlertType.INFORMATION); alert.setTitle("Sieg!"); alert.setHeaderText(""); @@ -266,13 +269,45 @@ public class Game alert.show(); controller.showNeutralUI(); + + try + { + controller.handler.unlockAchievement(0); + controller.handler.incrementAchievement(1, 1); + controller.handler.incrementAchievement(2, 1); + controller.handler.incrementAchievement(3, 1); + controller.handler.incrementAchievement(4, 1); + controller.handler.checkAllIncrementalAchievements(); + controller.handler.saveAndLoad(); + } + catch(Exception e) + { + } } else - { + { + player.resetWinsInARow(); + + try + { + if(controller.handler.getAchievements().get(3).getStatus().equals(Status.LOCKED)) + { + controller.handler.resetAchievement(3); + } + if(controller.handler.getAchievements().get(4).getStatus().equals(Status.LOCKED)) + { + controller.handler.resetAchievement(4); + } + controller.handler.saveAndLoad(); + } + catch(Exception e) + { + } + Alert alert = new Alert(AlertType.INFORMATION); alert.setTitle("Niederlage!"); alert.setHeaderText(""); - alert.setContentText(ais.get(currentPlayer - 2).getName() + " hat gewonnen."); + alert.setContentText(name + " hat gewonnen."); alert.initOwner(controller.stage); Stage dialogStage = (Stage)alert.getDialogPane().getScene().getWindow(); dialogStage.getIcons().add(controller.icon); diff --git a/src/logic/Player.java b/src/logic/Player.java index e6af68f3b94baac9d20c514a775e8b3a0cbb2f1d..b61e892bdb9298a9aa9a444604d372e2dd42483d 100644 --- a/src/logic/Player.java +++ b/src/logic/Player.java @@ -6,14 +6,14 @@ public class Player { private String name; private ArrayList<Card> deck; - private int wins; + private int winsInARow; private Game game; public Player(String name, Game game) { this.name = name; deck = new ArrayList<Card>(); - wins = 0; + winsInARow = 0; this.game = game; } @@ -24,17 +24,34 @@ public class Player public void win() { - wins++; + winsInARow++; } - public int getWins() + public void resetWinsInARow() { - return wins; + winsInARow = 0; + } + + public int getwinsInARow() + { + return winsInARow; } public void drawCard(Card card) { deck.add(card); + if(getNumberOfDrawFourCards() >= 2) + { + try + { + game.getController().handler.unlockAchievement(8); + game.getController().handler.saveAndLoad(); + } + catch(Exception e) + { + } + } + game.getController().setPlayerDeck(deck); } @@ -169,4 +186,17 @@ public class Player System.out.println("choose"); } } + + private int getNumberOfDrawFourCards() + { + int counter = 0; + for(Card card : deck) + { + if(card.getType().equals(CardType.DRAW_FOUR)) + { + counter++; + } + } + return counter; + } } \ No newline at end of file diff --git a/src/sounds/Sound.java b/src/sounds/Sound.java new file mode 100644 index 0000000000000000000000000000000000000000..b9ed37d395c0744260b85cb8b2f874681715c46c --- /dev/null +++ b/src/sounds/Sound.java @@ -0,0 +1,34 @@ +package sounds; + +import java.net.MalformedURLException; +import java.net.URISyntaxException; + +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; + +/** + * Klasse zum Laden und Abspielen einer MP3-Datei + * @author Robert + * + */ +public class Sound +{ + /** + * L�dt die angegebene MP3-Datei und spielt sie ab + * @param file String - Dateiname * + */ + public static void playSound(String file) + { + try + { + String path = Sound.class.getResource(file + ".mp3").toURI().toURL().toString(); + Media sound = new Media(path); + MediaPlayer mediaPlayer = new MediaPlayer(sound); + mediaPlayer.setAutoPlay(true); + } + catch(MalformedURLException | URISyntaxException e) + { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/sounds/unlocked.mp3 b/src/sounds/unlocked.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..fc3562c1d3c1a4cb3d58a2cffb2ff444197972d1 Binary files /dev/null and b/src/sounds/unlocked.mp3 differ