import javafx.application.Application; import javafx.application.Platform; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.stage.Stage; public class MainFX extends Application { private TextArea logArea; private Label heroLabel; private Label monsterLabel; private Button attackButton, specialButton, healButton, newGameButton; private ToggleButton autoToggle; private ProgressBar heroHpBar; private ProgressBar monsterHpBar; private Held hero; private Monster monster; private volatile boolean autoFightRunning = false; private Thread autoThread; private int healPotionCount = 3; // entry point public static void main(String[] args) { System.out.println("Starte JavaFX..."); launch(args); } @Override public void start(Stage primaryStage) { try { primaryStage.setTitle("RPG - JavaFX GUI"); VBox leftPane = new VBox(10); leftPane.setPadding(new Insets(12)); leftPane.setPrefWidth(300); Label chooseLabel = new Label("Held erstellen"); ChoiceBox typeChoice = new ChoiceBox<>(); typeChoice.getItems().addAll("Krieger", "Schurke", "Elf", "Zauberer"); typeChoice.setValue("Krieger"); // Waffenauswahl (für alle außer Schurke) Label weaponLabel = new Label("Waffe wählen:"); ChoiceBox weaponChoice = new ChoiceBox<>(); weaponChoice.getItems().addAll("Schwert", "Axt", "Dolch", "Sichel"); weaponChoice.setValue("Schwert"); Label materialLabel = new Label("Material:"); ChoiceBox materialChoice = new ChoiceBox<>(); materialChoice.getItems().addAll("Eisen", "Holz", "Knochen", "Stahl"); materialChoice.setValue("Eisen"); TextField nameField = new TextField(); nameField.setPromptText("Name des Helden"); newGameButton = new Button("Neues Spiel"); newGameButton.setMaxWidth(Double.MAX_VALUE); attackButton = new Button("Angreifen"); specialButton = new Button("Spezialangriff"); healButton = new Button("Heiltrank benutzen"); autoToggle = new ToggleButton("Automatisch kämpfen"); for (ButtonBase b : new ButtonBase[] {attackButton, specialButton, healButton, autoToggle}) { b.setMaxWidth(Double.MAX_VALUE); b.setDisable(true); } leftPane .getChildren() .addAll( chooseLabel, typeChoice, weaponLabel, weaponChoice, materialLabel, materialChoice, nameField, newGameButton); // Typ-Wahl: Wenn Schurke gewählt ist, Waffenauswahl deaktivieren, Spezial nur für Schurke/Elf typeChoice.setOnAction( ev -> { String t = typeChoice.getValue(); boolean isRogue = "Schurke".equals(t); weaponChoice.setDisable(isRogue); materialChoice.setDisable(isRogue); specialButton.setDisable(!("Schurke".equals(t) || "Elf".equals(t))); }); VBox rightPane = new VBox(10); rightPane.setPadding(new Insets(12)); rightPane.setAlignment(Pos.TOP_LEFT); heroLabel = new Label("Held: ---"); heroHpBar = new ProgressBar(0); heroHpBar.setPrefWidth(600); monsterLabel = new Label("Monster: ---"); monsterHpBar = new ProgressBar(0); monsterHpBar.setPrefWidth(600); logArea = new TextArea(); logArea.setEditable(false); logArea.setWrapText(true); logArea.setPrefSize(600, 340); // Action buttons über der Anzeige (log) HBox actionBox = new HBox(8); actionBox.setAlignment(Pos.CENTER_LEFT); actionBox.getChildren().addAll(attackButton, specialButton, healButton, autoToggle); rightPane .getChildren() .addAll( heroLabel, heroHpBar, monsterLabel, monsterHpBar, actionBox, new Label("Spiel-Log:"), logArea); Label infoLabel = new Label("Tipps: Spezialangriff verursacht mehr Schaden. Heiltränke = begrenzt."); BorderPane root = new BorderPane(); root.setLeft(leftPane); root.setCenter(rightPane); root.setBottom(infoLabel); BorderPane.setAlignment(infoLabel, Pos.CENTER); BorderPane.setMargin(infoLabel, new Insets(8)); Scene scene = new Scene(root, 960, 550); primaryStage.setScene(scene); primaryStage.show(); // --- Event Handler --- newGameButton.setOnAction( e -> { String type = typeChoice.getValue(); String name = nameField.getText().trim(); if (name.isEmpty()) name = type; String weapon = weaponChoice.getValue(); String material = materialChoice.getValue(); createNewGame(type, name, weapon, material); }); attackButton.setOnAction(e -> runOneRound(false)); specialButton.setOnAction(e -> runOneRound(true)); healButton.setOnAction(e -> useHealPotion()); autoToggle.setOnAction( e -> { if (autoToggle.isSelected()) startAutoFight(); else stopAutoFight(); }); primaryStage.setOnCloseRequest( e -> { stopAutoFight(); Platform.exit(); System.exit(0); }); appendLog("Willkommen zum RPG (GUI). Erstelle zuerst einen Helden."); } catch (Exception e) { e.printStackTrace(); } } // ---- Ab hier: deine Spiellogik-Methoden ---- private void createNewGame(String typ, String name, String weaponType, String material) { try { Waffe weapon = new Waffe(weaponType, material); if (typ.equals("Krieger")) { hero = new Krieger(name, 30, 6, 1.2); } else if (typ.equals("Schurke")) { // Waffen in Schurken anders genutzt Waffe dolch = new Waffe("Dolch", "stahl"); Waffe axt = new Waffe("Axt", "stahl"); hero = new Schurke(name, 24, 5, dolch, axt); } else if (typ.equals("Zauberer")) { hero = new Zauberer(name, 22, 5); } else { hero = new Elf(name, 22, 5); } hero.setWaffe(weapon); monster = generateMonster(); healPotionCount = 3; appendLog( String.format( "Neues Spiel gestartet: %s (%s) vs %s HP:%d DMG:%d", hero.getName(), hero.getTyp(), monster.getName(), monster.getHp(), monster.getDamage())); updateStatusLabels(); for (ButtonBase b : new ButtonBase[] {attackButton, specialButton, healButton, autoToggle}) { b.setDisable(false); } // Spezial nur für Schurke und Elf specialButton.setDisable(!("Schurke".equals(typ) || "Elf".equals(typ))); } catch (Exception ex) { appendLog("Fehler beim Erstellen des Helden: " + ex.getMessage()); ex.printStackTrace(); } } private Monster generateMonster() { String[] names = {"Goblin", "Zombie", "Ork", "Skelett", "Troll", "Drache"}; String name = names[(int) (Math.random() * names.length)]; int baseHp = 18 + (int) (Math.random() * 10); int baseDmg = 3 + (int) (Math.random() * 5); Monster m = new Monster(baseHp, baseDmg, name); return m; } private void runOneRound(boolean special) { if (hero == null || monster == null) return; if (hero.getHp() <= 0 || monster.getHp() <= 0) return; if (special) { // Spezialfähigkeiten nur für Elf (SpeedBoost) und Schurke (Doppelangriff) if (hero instanceof Elf) { ((Elf) hero).speedBoostAktivieren(); appendLog(hero.getName() + " aktiviert SpeedBoost!"); hero.angreifen(monster); } else if (hero instanceof Schurke) { // Spezieller Schurke-Angriff: wechselt zur Axt, führt Angriff aus, dann normaler Angriff String msg = ((Schurke) hero).specialAngriff(monster); appendLog(msg); if (monster.getHp() > 0) { // zusätzlich ein normaler Folgeangriff hero.angreifen(monster); appendLog(hero.getName() + " greift nach dem Spezialangriff erneut an!"); } } else { appendLog("Spezialfähigkeit nicht verfügbar für " + hero.getTyp()); hero.angreifen(monster); } } else { hero.angreifen(monster); appendLog(hero.getName() + " greift an!"); } updateStatusLabels(); if (monster.getHp() <= 0) { appendLog("Monster " + monster.getName() + " besiegt!"); disableActions(); return; } int mdmg = monster.getDamage(); hero.setHp(hero.getHp() - mdmg); appendLog(monster.getName() + " kontert für " + mdmg + " Schaden!"); updateStatusLabels(); if (hero.getHp() <= 0) { appendLog(hero.getName() + " ist gefallen. Spiel Ende."); disableActions(); } } private void disableActions() { for (ButtonBase b : new ButtonBase[] {attackButton, specialButton, healButton, autoToggle}) { b.setDisable(true); } autoToggle.setSelected(false); stopAutoFight(); } private void useHealPotion() { if (healPotionCount <= 0) { appendLog("Keine Heiltränke mehr!"); return; } hero.setHp(hero.getHp() + 10); healPotionCount--; appendLog(hero.getName() + " trinkt einen Heiltrank (+10 HP). Verbleibend: " + healPotionCount); updateStatusLabels(); } private void updateStatusLabels() { if (hero != null) { heroLabel.setText( String.format( "Held: %s (%s) DMG: %d Heiltränke: %d", hero.getName(), hero.getTyp(), hero.getDamage(), healPotionCount)); double hpFraction = hero.getMaxHp() > 0 ? (double) hero.getHp() / hero.getMaxHp() : 0; heroHpBar.setProgress(Math.max(0.0, Math.min(1.0, hpFraction))); heroHpBar.setTooltip(new Tooltip(hero.getHp() + " / " + hero.getMaxHp())); } else heroLabel.setText("Held: ---"); if (monster != null) { monsterLabel.setText( String.format( "Monster: %s HP: %d DMG: %d", monster.getName(), monster.getHp(), monster.getDamage())); double mhpFraction = monster.getMaxHp() > 0 ? (double) monster.getHp() / monster.getMaxHp() : 0; monsterHpBar.setProgress(Math.max(0.0, Math.min(1.0, mhpFraction))); monsterHpBar.setTooltip(new Tooltip(monster.getHp() + " / " + monster.getMaxHp())); } else monsterLabel.setText("Monster: ---"); } private void appendLog(String text) { Platform.runLater(() -> logArea.appendText(text + "\n")); } private void startAutoFight() { if (autoFightRunning) return; autoFightRunning = true; appendLog("Auto-Kampf gestartet."); autoThread = new Thread( () -> { while (autoFightRunning && hero.getHp() > 0 && monster.getHp() > 0) { Platform.runLater(() -> runOneRound(false)); try { Thread.sleep(800); } catch (InterruptedException ignored) { } } Platform.runLater( () -> { autoToggle.setSelected(false); appendLog("Auto-Kampf beendet."); }); autoFightRunning = false; }); autoThread.setDaemon(true); autoThread.start(); } private void stopAutoFight() { autoFightRunning = false; if (autoThread != null) autoThread.interrupt(); } }