Java Textadventure

merlin123

Lt. Commander
Registriert
Jan. 2018
Beiträge
1.832
Hallo Zusammen!

Ich bin im Moment dabei ein Textadventure in Java zu programmieren und stoße im Moment auf einige Probleme.

Folgendes stelle ich mir vor:

Man hat eine Ausgabe mit verschiedenen Antwortmöglichkeiten das den Spielfluss beinflusst.
Eine Extramethode die nur für den Kampf zuständig ist, ist bereits in Arbeit.
Spieler und Gegner greifen sich gegenseitig an, dabei hat der Spieler die Möglichkeit zwischen 1/2/3 Möglichkeiten zu entscheiden um den Ablauf zu gestalten.
Ich würde mir wünschen das man durch verschiedene Gegenstände seine Angriffsstärke sowie defensive steigen kann. Diese werden vom Gegner fallen gelassen (zufällig?) und automatisch aufgerüstet. Man hat die Möglichkeit sich zu heilen und Tränke zu erhalten.


1. Meine Frage wäre, wie ich es schaffe ein Textadventure mit einer fortlaufenden Handlung und ein "Kampfsystem" miteinander zu verknüpfen?

Meine Überlegung dazu wäre das Hauptspiel mit Erzählungen und Entscheidungsmöglichkeiten in eine Main Methode zu packen das dann immer auf die Methode "Kampf" zugreift falls es zu einem Konflikt kommt. Leider habe ich keinerlei Ahnung ,ob das was ich mir denke überhaupt so möglich ist oder ob man es anders macht.

2. Ich habe bisher ein Auswahlsystem im Kampfmodus erstellt, aber falls die Lebenspunkte den Stand 0 erreichen rechnet das Programm immernoch weiter in den negativen Bereich. Ein Ende gibt es bisher nicht.

3. Wie verlasse ich eine Kampfsituation und fahre dann mit den Auswahlmöglichkeiten fort? Vorgestellt hatte ich mir das mit einer Ausgabe die in etwa lautet "Du fliehst in Schande". Aber Woher weiß das Programm das es wieder in der Hauptmethode ist? Anders gesagt was macht das Programm nach einem Kampf?

Hier mal mein Code :/

Java:
package textadventuretime;

import java.util.Random; //importe
import java.util.Scanner; //importe

public class textadventuretime {

    public static void main(String[] args) {

        //Spiel Objekte
        Scanner in = new Scanner(System.in); // Tastatureingabe
        Random rand = new Random(); // gibt zufaellige Zahlen aus, wichtig fuer das Array

        //Variablen des Spieles
        String[] Gegner = {"Skelett", "Baer", "alte Hexe", "Schlange"}; // wird in Array angelegt sodass man ein Pool hat aus dem Gegner zufällig gewählt werden
        int maxGegnerLeben = 100; // soviel Leben kann ein Gegner Maximal haben
        int GegnerSchaden = 10; // soviel macht jeder Gegner an Schaden

        //Variablen des Spielers
        int maxLeben = 150; //maximales Leben des Spielers
        int AngriffsSchaden = 25; // 25 Schaden pro Zug
        int Heiltrank = 15; // 15 Einheiten an Heilung
        int HeiltrankHeilung = 30; // Heilungseffekt pro Trank
        int HeiltrankDropChance = 50; // stellt Prozentzahl dar wie oft ein Trank erhalten werden kann

        boolean rennen = true; // Spiel lädt solange weiter bis man es selbst stoppt

        System.out.println("Wilkommen in der Gruft"); // Begruessungstext des Spieles

        GAME: // while loop wird mit einem label versehen, sodass man nur GAME eingibt um die whileschleife aufzurufen
        while (rennen) {
            System.out.println("------------------------------------");

            // Das Leben des Gegners wird zufaellig ausgegeben, aber nicht ueber das Maximum
            int enemyHealth = rand.nextInt(maxGegnerLeben);
            String enemy = Gegner[rand.nextInt(Gegner.length)]; // Gegner wird aus Array zufällig ausgelesen mit .length zwischen 0 und max länge des array
            System.out.println("\t# " + enemy + " erscheint! #\n");

            while (enemyHealth > 0) {

                System.out.println("\tDeine HP: " + maxLeben);
                System.out.println("\t" + enemy + "'s HP: " + maxGegnerLeben);
                System.out.println("\n\t Was willst du tun?");
                System.out.println("\t1. Eins ueber die Ruebe hauen");
                System.out.println("\t2. Eine Runde chillen");
                System.out.println("\t3. Wegrennen wie ein Feigling?");

                System.out.println("------------------------------------");
                /*Hier wird eine Eingabe vom Spieler verlangt mit den Tasten
                    1/2/3 die verschiedene Handlungen ausführen*/
                String input = in.nextLine();
                //2 Variabeln bei Angriff, geben zufälligen Schaden an
                if (input.equals("1")) {
                    int SchadenAusgeteilt = rand.nextInt(AngriffsSchaden);
                    int SchadenGenommen = rand.nextInt(GegnerSchaden);
                    //Hier wird der Schaden vom Leben des Gegners abgezogen   
                    maxGegnerLeben -= SchadenAusgeteilt;
                    // Hier wird der Schaden vom Leben des Spielers abgezogen
                    maxLeben -= GegnerSchaden;
                    // Ausgabe des Angriffsvorganges
                    System.out.println("\t> Der Gegner " + enemy + " erleidet Schaden mit dem Wert " + SchadenAusgeteilt + " Schadenspunkte.");
                    System.out.println("\t> Du erleidest " + SchadenGenommen + " als Konter");

                    // Bei erreichen von 0 Lebenspunkten
                    if (maxLeben < 1) {
                        System.out.println("\t> Deine Lebenspunkte sind verbraucht.");
                        break; // befördert einen aus der if Schleife heraus
                    }

                } else if (input.equals("2")) {

                } else if (input.equals("3")) {

                } // Bei falscher Eingabe wird wieder in die whileSchleife gesprungen
                else {
                }
            }// Bei Game over wird dieser Text ausgegeben
            System.out.println("Du stirbst an deinen Verletzungen");
        }
    }
}
 
Mal so generell an den objektorientierten Ansatz gedacht?

Spaghetti Code in der Main Methode ist bei der Verwendung von Java schon echt bitter.

Die Antwort zu verschiedene Waffen, die Einfluss auf das Kampfgeschehen haben, weisen eigentlich geradezu darauf hin, dass du dir mal Gedanken darüber machst, das ganze Klassentechnisch aufzufächern.

Z.B.: Waffe (Vaterklasse) -> Schwert (Kindklasse) / Axt (Kindklasse)

Dann würde eine entsprechende Kampffunktion an dieser Stelle einfach mit einer Waffe arbeiten, die Unterschiede kämen durch das jeweilige Kind-Objekt zu Stande.

Hier hast du wohl einfach drauflosprogrammiert und bist in einer Sackgasse gelandet. Alles nochmal neu, so nicht.
 
Hi, vorweg erstmal zu dem Programmierstil (du bist Anfänger von daher klar, dass du das so machst :D)
Die main-Methode ist an sich nicht gedacht alles zu erschlagen, die ruft in aller Regel nur deine weiteren Methoden auf und ist wirklich nur der Einstieg, stellt selbst aber keine weiteren Funktionen bereit - dafür gib es weitere Methoden (und Klassen). Weiterhin musst du nicht an jede Zeile einen Kommentar schreiben (zB Zeile 16), man sagt immer Kommentare dort wo sie für das Verständnis wirklich nötig sind oder Bereiche unterteilen - für den Rest nutzt man selbstbeschreibende Funktions-/Klassen-/Variablennamen.
Ergänzung ()

Wie Grimba schon sagt: denke mal über einen OOP (Objektorientiert) Ansatz nach, wenn du dich damit bisher nicht beschäftigt hast mache vlt erstmal ein kleines Beispiel so wie du es bisher hast. Aber für ein ganzes Spiel tust du dir selber keinen Gefallen und gewöhnst dir unter Umständen nur einen schlechten Stil an. Da du bisher auch nicht mit Methoden gearbeitet hast würde ich dort ersteinmal anfangen und Teile des Codes in Funktionen auslagern, die du dann aufrufen kannst, dann weißt du auch gleich wie du das mit dem Abbruchkriterium machen kannst und wieder in den Dialog nach dem Kampf zurückkehrst ;). Wenn du das beherrschst kannst du dir Klassen anschauen und dann vor allem erstmal dein Spieelkonzept überlegen, anstatt einfach darauflos coden :D
Ich empfehle dir sonst auch https://www.codingame.com/ - dort kannst du ganze nett die Grundkonzepte lernen.
 
Zuletzt bearbeitet:
Das heißt also das ich eine main Methode erstelle die mir dann meine Methoden die ich brauche aufruft?

Klassentechnisch habe ich mir schon meine Gedanken gemacht, ich weiß aber nicht wie man das alles zusammenführt. Ich habe ja schon Probleme die "Erzählung" seperat vom "Kampfsystem" zu machen
 
zu Punkt 2: In Zeile 67 das break, ist nicht richtig da ein if keine Schleife ist aus der du raus springst, sondern eine Kontroll-Anweisung. hier müsstest du z.b. eine Bedingung deiner while Schleifen negieren sodass die Schleife abbricht.
 
@00Zetti: Ist die Seite die du mir empfiehlst gut? Habe bisher nur in der Schule, auf Lynda.com und bei TheSimpleClub Videos und Übungen zu Java gemacht. Ist deine Seite auch kostenlos?
 
Ich habe ein paar jahrelang Studenten unterrichtet und dort immer die Seite empfohlen, bisher kam nur gutes Feedback. Und ja sie ist kostenlos.
 
Such mal in Google "Coding Challanges". Das sind Seiten mit Aufgaben die immer schwerer werden. Programmieren ist mehr das Problem durchdenken, dann in Code ausdrücken. Später auf der Arbeit programmiert man vielleicht 20-30%, den Rest der Zeit verbringt man mit Planung und Analyse.
 
merlin123 schrieb:
Ich habe ja schon Probleme die "Erzählung" seperat vom "Kampfsystem" zu machen
Dann mach mehrere Klassen daraus, Story, Spieler und Gegner zB.

Story könnte z.B. die Story und den Game Ablauf steuern (ich denke das Game bleibt simpel genug um das zu erlauben) und dann bei Bedarf Spieler und Gegner Objekte erstellen und diese miteinander interagieren lassen (Kampf und Dropsystem). Das Spielerobjekt könnte auch nur einmal am Anfang erstellt werden und dann im Speicher gehalten werden.
 
Du wirst, ohne eine Ahnung davon zu haben, wie Klassen und Objekte in Java funktionieren, sehr schnell an eine natürliche Grenze laufen, denn für iterativen Code (das ist das, was du machst: Hauptmethode + Funktionen), ist Java nicht gemacht worden. Du vergibst dir im Falle von Java dadurch soviel, weil du es nicht nutzt. Für sowas, was du machst, wäre z.B. C gemacht.

Es ist aber wahr, dass man als Anfänger vielleicht nicht gleich mit einem Textadventure anfängt. Es wäre, wie bereits genannt, von Nutzen, wenn du mit kleinen, sich im Schwierigkeitsgrad steigernden Übungsaufgaben anfängst, um ein Gefühl für die Sprache und das Problemlösen zu bekommen. Wie ich sehe bist du ja in den Grundlagen schon sehr weit. Aber diese Umsetzung dort, muss, für das was du vorhast, scheitern.

Du findest den Grund dafür sowohl in dem Problem, was du beschreibst: "Wie bekomme ich Story und Spielablauf getrennt" genauso wie im Quellcode:
Code:
int Heiltrank;
oder
Code:
String[] Gegner {"Skelett", "Bär", "alte Hexe", "Schlange"};

Das Schreit ja geradezu laut danach, dass du dir Klassen zu Heiltrank bzw. Gegner machst, und dann entsprechende Kindklassen Genger->Bär. Denn offensichtlich ist weder int noch String[] das Konzept eines Heiltrankes bzw. Gegnerbären bekannt.

Und nun kommen wir wieder zu deinem Problem zurück, Story mit Spielablauf zu verdrahten. Hier verhält es sich eben auch ähnlich. Warum müssen die denn fest verdrahtet sein? Wäre es nicht sinnvoller eine Spielengine zu haben, die die grundlegenden Mechaniken zur Verfügung stellt, z.B. Kampf, Inventar, Spielerfunktionen, Gegnerfunktionen, Navigation, Kommunikation und du eine weiteres getrenntes Modul für die Story hast, die dann zu den gewünschten Zeitpunkten die entsprechenden Funktionen ausführt? So kannst du die gleiche Engine für beliebig viele Stories verwenden. Eines DER Zauberwörter bei objektorientierten Programmierung ist nunmal Wiederverwendbarkeit von Code. :)

Ich bin jetzt kein Spieldesigner, aber je weniger fest miteinander verdrahtet ist, desto weniger musst du hinterher programmieren, weil du Probleme nicht mehrmals lösen musst.

Da du ja wirklich die Grundlagen der Syntax schon verstanden zu haben scheinst, würde ich dir wirklich direkt raten, dich mal mit Klassen und Objekten zu beschäftigen.
 
Hallo,
genauso wie rob- bin ich der Meinung, dass du dir erstmal gedanken darüber machen solltest, was GENAU dein Programm können soll, wie die Mechaniken ablaufen sollen etc. Am Besten du schreibst es nieder. Dabei kommen oft weiterführende und neue Gedanken. Wenn du das gemacht hast, kannst du dir Gedanken darüber machen, wie du die Software aufbaust, sprich welche Klassen benötigst du, welche Objekt müssen wie interagieren und welche Schnittstellen werden dazu benötigt (welche Methoden werden benötigt, wie und vom wem werden sie aufgerufen (manueller oder eventbasierender Methodenaufruf) etc.). Dies bitte ebenfalls schriftlich festhalten.

Nun kannst du ans implementieren gehen.

greetz
hroessler
 
Ich könnte dann also eine Klasse "Gegner" erstellen mit verschiedenen Objekten,richtig?

Code:
package textadventuretime;

public class Gegner {
//Objekte der Klasse Gegner werden erstellt

    Gegner Skelett = new Gegner();
    //Atributte des Skeletts werden festgelegt
    int maxSkelettLeben = 100; // soviel Leben kann ein Skelett Maximal haben
    int SkelettSchaden = 10; // soviel macht jeder Skelett an Schaden
    
    Gegner Baer = new Gegner();
    //Atributte des Wolfes werden festgelegt
    int maxBaerLeben = 150; // soviel Leben kann ein Baer Maximal haben
    int BaerSchaden = 20; // soviel macht jeder Baer an Schaden
    
    Gegner alte_Hexe = new Gegner();
    //Atributte der alten Hexe werden festgelegt
    int maxalte_HexeLeben = 75; // soviel Leben kann eine alte_Hexe Maximal haben
    int alte_HexeSchaden = 35; // soviel macht jede alte_Hexe an Schaden
    
    Gegner Schlange = new Gegner();
    //Atributte der Schlange werden festgelegt
    int maxSchlangeLeben = 50; // soviel Leben kann eine Schlange Maximal haben
    int SchlangeSchaden = 5; // soviel macht jede Schlange an Schaden
}

Und diese dann in der main-Methode als Gegner(); "zur Verfügung" stellen, deswegen public class Gegner?
Oder muss ich für jedes Gegnerobjekt seperat eine Klasse erstellen?
Bitte um ein Erklärung,aus dem Internet werde ich nicht schlaus draus. :(
 
Du solltest für jede Kindklasse von Gegner, sagen wir Bär, eine eigene Klasse erstellen, und diese Explizit von Gegner erben lassen. Damit kann Bär dann alles, was Gegner kann, zusätzlich zu seinen eigenen Funktionen bzw. er kann vorhandene überschreiben.

Das, was du da machst, ginge schon, aber dann hast du einfach viele Gegner mit verschiedenen Namen. Aber es sind Gegner. Deine Syntax ist trotzdem Murks, da sowas wie MaxLeben etc. Membervariablen von Gegner wären. Die jetzt in der Main zu definieren ist totaler Kokolores.
 
Grimba schrieb:
Du musst für jede Kindklasse von Gegner, sagen wir Bär, eine eigene Klasse erstellen, und diese Explizit von Gegner erben lassen. Damit kann Bär dann alles, was Gegner kann, zusätzlich zu seinen eigenen Funktionen bzw. er kann vorhandene überschreiben.

Die Syntax, die du da schreibst, ist leider... Murks :)

Kannst du mir das zeigen wie man das macht?
Und zur Syntax, was genau meinst du? In der Schule haben wir das so gelernt das man zb Arraylist testlist = new ArrayList(); schreibt um ein neues Objekt anzulegen.

Wie schreibe ich den in meine Main methode das ich etwas aus einer anderen Methode verwenden will?
 
Konzepte der Objektorientierten Programmierung im Allgemeinen und deren Anwendung bei der Programmierung von Computerspielen im Speziellen, sind leider umfangreicher, als dass man sie in einem oder mehreren Forenbeiträgen abhandeln kann.

Daher empfehle ich dir zwei kostenlose Bücher, die alles behandeln, was hier angesprochen wurde und noch viel mehr:
Gerade das Kapitel II von Game Programming Patterns wird dir hier sehr weiterhelfen.
 
Ack der III hat Recht. Ich geb dir nur ganz kurz mal ein paar Punkte, die so nicht richtig sind an dem Code, dann merkst du schnell, dass dir das Zwischenwissen fehlt. Und das musst du dir einfach aneignen, da führt kein Weg drumrum und auch keine kurze Erklärung hin.

1. Du hast keine main methode mehr, sondern nur noch eine Klassendeklaration. Das Programm kann nicht mehr ausgeführt werden.
2. Du erstellst in der Klassendeklaration weitere Objekte von der Klasse, die du eigentlich gerade beschreiben willst und rufst mit new Gegner() einen Kunstruktor auf, den du noch nicht einmal hast.
3. Dass das alles "nur" Gegner sind, aber eben nicht ein Skelett, was auch ein Gegner ist, aber seine ganz eigenen Werte und Funktionen hat, hatte ich ja schon gesagt. Das damit zu lösen, dass man dann in Gegner einfach alle Membervariablen hineinpackt, die eigentlich zu Kindklassen gehören, ist dann einfach Kokolores. Das ist dann wieder so ähnlich wie alles in die Main packen.

Was dir fehlt ist die Bedeutung der Begriffe Klassendeklaration, Objekte, Vererbung, was ein Konstruktur ist, was Member sind, sowie, was genau "new" tut. Ein "Der Lehrer hat gesagt, dass man das so hinschreiben muss" erklärt dir nicht das warum. Das sprengt aber den Rahmen dieses Forums, daher kommst du um ein Javatutorial nicht herum. Sei es online oder in Buchform
 
Soweit sind wir noch garnicht in der Schule. Bisher hatten wir Schleifen/Arrays/Mehrdimensionale Arrays.
Ich würde aber gerne etwas praktisches Programmieren bei dem ich auch einen "Nutzen" habe deswegen habe ich mir sowas wie ein Textadventure ausgesucht. In der Schule haben wir nochnichtmal Methoden angesprochen. Ich bringe mir im Moment alles selbst bei.
 
Ja, weil du denkst, dass das einfach ist. Ist es aber nicht.

Spätestens beim Parser, der die Nutzerbefehle in Aktionen umwandelt (DAS Herzstück jedes Textadventures), wird's wieder knifflig.

Zum Programmieren gehört auch, dass man ein gewisses Verständnis für Problemkomplexitäten hat. Wie schon vorher gesagt wurde, gutes Design verbraucht hinterer mehr Arbeit als das reine Programmieren. Einfach drauflos zu programmieren führt genau dahin, wo du jetzt bist. Irgendwann kommt der Punkt, wo du dir sagst "So, jetzt hab ich das und das schon, jetzt brauch ich noch das andere und..... oh... das funktioniert aber dann nicht mit dem bisherigen und... oh, da muss ich ja das hier alles umschreiben, und wie bekomme ich eigentlich ne Story in das Spiel...." und dann sagt mir hier noch einer, dass das alles Murks, ist, dabei hab ich mir so ne Mühe gegeben.... Merkste selber, ne? ;) Ein "dann muss es dafür doch auch ne Lösung geben" ist ein frommer Wunsch, wäre auch prima, aber geh da mal nicht immer von aus, sonst wäre mein Beruf nämlich echt himmlisch.

Das soll dich nicht davon abhalten, das zu tun, um Gottes Willen nein. Ich sage nur: Dir fehlen dafür zu viele Grundkonzepte um dein Vorhaben mit deinem jetzt vorhandenen Wissen umzusetzen.

Daher war der Vorschlag mit den stetig im Schwierigkeitsgrad steigenden Übungsaufgaben schon sehr richtig.

Mein Tipp:
Damit du dein Vorhaben nicht ganz aufgeben musst, mach es anders:

Schreibe Komponenten des großen Ganzen. Kleine Programme, die zu einem Input einen gewünschten Output liefern. Z.B. hast du hier ja einen Kampf. Schreibe ein einfaches Programm, dass einen Kampf ausführt von gedachten Gegnern, also INPUT: Gegner 1, Gegner 2 und OUTPUT: Sieger.

Oder schreib ein Programm, dass sicherstellt, dass wenn du "N" eintippst, die Richtung Norden eingeschlagen wird etc. Also INPUT "N" OUTPUT: Norden

Vielleicht merkst du wo das hinführt. Sagen wir du hast irgendwas kampfmäßiges geschrieben. Dann wirst du dir Gedanken machen, was das wohl für Gegner sein könnten. Dann gilt es, möglichst ohne diesen Code komplett wegzuschmeißen, ihn so abzuändern, dass verschiedene Gegner gegeneinander Kämpfen können.... etc. etc.

Oder beim anderen denkst du erst: Es wäre toll, wenn auch andere Richtungen gingen. Dann baust du alle anderen Richtungen ein. Dann überlegst du dir vielleicht, dass es ja vielleicht manchmal nicht möglich ist, dass in eine Richtung gegangen werden kann, und baust eine Möglichkeit ein, den weg zu verweigern. usw usw.

Und dann vielleicht ein Storymodul, dass erstmal nichts anderes macht als dass der Held nach Norden läuft und dort kämpft. Und zwar mit dem was du schon hast. Und dann kommen dir vielleicht neue Ideen....

Stück für Stück strickt sich dein Textadventure zusammen. Nicht gleich alles wollen, sondern kleine Komponenten, von ganz simpel nach komplex aufbauen und zusammenstricken. Mit der Prämisse, dass die kleinen Komponenten für sich gesehen auf jeden Fall funktionieren.

Nebenbei schön weiter tutorials lesen. Viel Spaß! :)
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: 00Zetti, TPZ und Madman1209
Ich habe nirgendswo gemeint oder geschrieben das das einfach ist, also bitte nichts erfinden!

Ich habe mir dieses "Projekt" einfach als Ziel gesetzt ,weil wir in der Schule rein nichts praktisches machen.
Was bringt es mir Arrays zu sortieren, aus Schleifen herauszuspringen oder Rechenoperationen durchzuführen wenn ich keinerlei praktischen Nutzen darin habe?

Unsere Lehrer machen seit Rund 2-3 Monaten nur Arrays, aber was Methoden, Operatoren und Objekte/Attribute sind wurde bisher nicht erwähnt. Deswegen MUSS ich mir solche Sachen selbst aneignen.

Ich will auch nicht ALLES auf einmal sondern Stück für Stück LERNEN was bestimmte Befehle überhaupt machen.

Deswegen habe ich alles in die MAIN Methode geschrieben weil wir das bisher im Unterricht auch immer gemacht haben, da war nie die Rede das man durch die Main seine Methoden Aufruft.

Es ist einfach frustrierend das man das in der Schule lernen "sollte" aber nach 6 Monaten immernoch dasselbe macht ohne einen Fortschritt :/
 
Ein Ziel zu haben / sich zu setzen ist eine wunderbare Sache. Aber macht deutlich kleinere Schritte.
Setzt dir kleine Probleme / Ziele und arbeite dich daran langsam hoch.
 
Zurück
Oben