# Spielkapitel/-Level erstellen/verwalten



## Mofi (29. Nov 2011)

Huhu ihrs 
Ich weiß der Titel ist komisch gewählt, aber mir viel nichts sinnvolleres ein.
Ich steh momentan (mal wieder) kurz vor der Frage...Wie soll man denn ein naja Level-/Kapitelsystem entwickeln.
Bisher hab ich einige Spiele angefangen und bei genau diesem Punkt immer aufgehört und was anderes gemacht bzw. ein neues Spiel (bzw. neue Art) angefangen...

Aber diesmal wollt ich es dann doch zuende machen, da ich einiges an Zeit reingesteckt habe und auch ne Menge Quellcode (wobei das natürlich subjektiv ist und auch auf die Vorgänger zutrifft...)

Ich versuch mal es irgendwie sinnvoll zu erklären.
Man hat im Endeffekt ja immer eine Welt die mehrere Level oder "Räume" hat. Die irgendwie verbunden werden müssen (nicht so sehr das Thema). Aber wie erstelle ich diese sinnvollerweise(!!) für mein Spiel. Ich mein wir reden da ja nicht von nur 2 - 5, sondern von sehr vielen (Teilweise). Und jedes Level/Raum hat ja auch Gegner, Items etc.
Ich kann natürlich tausende von Codezeilen schreiben um dies zu implementieren...Aber ich denke es gibt eine sinnvollere Lösung (es MUSS eine geben...^^)

Irgendwie hab ich mir nie ein richtiges Konzeot dafür vorstellen können...

Vielleicht hilft es, wenn ich euch kurz erläutere was für eine Art Spiel ich mache, da diese sich ja doch "etwas" unterscheiden könnten.

Mein Spiel findet momentan in einer JTextArea statt, da es komplett Textbasiert ist. Die Befehle werden in einem JTextField eingebenen.
So kann man sich momentan durch die (sehr kleine) Spielwelt bewegen und (mittlerweile...War ein ganz schöner Krampf) Sachen einsammeln. Stellenweise auch gegen Monster kämpfen.
Dies funktioniert alles nur rudimentär und ist nicht perfektioniert. (Es ging erstmal ums funktionieren)
Das alles ändert aber nichts daran, dass es mal ein Spielbares Spiel werden soll. Aber dazu braucht man sehr viele "Räume" die der Spieler betreten kann und wo halt NPC/Gegner/Items drin sind. 
Dazu wollen diese Räume aber alle erstellt und verwaltet werden. NPC/Gegner/Items wollen auch pro Raum erstellt werden...
Mir fällt aber keine sinnvolle Lösung ein um dies möglichst effizient und wiederbenutzbar zu ermöglichen. 

Vielleicht habt ihr ja Ideen.

Ehrlich gesagt bin ich grad hin und hergerissen, ob ihr Quelltext braucht um mir ein wenig auf die Sprünge zu helfen...Wenn ja müsst ihr euch melden...Es ist nicht der schönste...Vorallem die Sachen die nach und nach dazu kamen, weil ich irgendwann das kommentieren weggelassen hab 

So danke fürs lesen des langen Textes...Eigentlich wollte ich zuerst nichts schreiben, aber alleine komme ich auch einfach nicht weiter, weil ich bei dem Thema wie gesagt schon immer festgesteckt hab...

Gruß
Mofi


----------



## Ralph-Uwe (29. Nov 2011)

Hi MoFi

mein Vorschlag wäre, Collections mit den für jeden Raum zu erstellen.
Diese Collections enthalten z.B. die Raumgröße, Hintergundbild usw. und vorallem 
weitere Collections für Gegener, Invertar....(was auch immer benötigt wird).
Die Collection der Räume können wiederum in einer Collection gespeichert werden,
die nacher Deiner gesamten Welt entspricht.

Ich hoffe, damit weitergeholfen zu haben.  

Gruß


----------



## Marco13 (29. Nov 2011)

Ja... worum geht es? Doch offenbar nicht um eine Klassenstruktur, oder? Damit wäre ja schon weitgehend vorgegeben, welche Informationen es zu einem "Raum" überhaupt geben kann. Also, wenn es da schon ein paar Interfaces gibt, wäre es wohl nicht so verkehrt, die zu posten. 

Für die "Verwaltung" im Sinne der Erstellung und so... läuft das auf ein einfaches Dateiformat hinaus? Vielleicht auch pragmatischerweise XML
[XML]
<room id="0001">

    <items>
        <item><healthPotion powerUp="31"></item>
        <item><sword damage="23"></item>
    </items>

    <opponents>
        <opponent><ogre strength="100"></opponent>
    </opponents>

    <doors>
        <door from="0001" to="0002" />
    </doors>

</room>
[/XML]

 :bahnhof:


----------



## Mofi (29. Nov 2011)

Also meine Raumklasse sieht momentan so aus:


```
package model;



import java.util.*;



import model.figuren.Gegner;



public class Raum {

	/** Beschreibung des Raumes */

	private String beschreibung;

	/** Der Name des Raumes */

	private String name;

	/** Alle moeglichen Ausgaenge aus diesem Raum */

	private ArrayList<Ausgang> ausgaenge;

	/** Liste mit den Monstern/Gegnern die diesen Raum besiedeln */

	private ArrayList<Gegner> gegnerliste;

	/** Ist der Raum ein sicherer Raum? Also keine Monster vorahnden == sicher*/

	private boolean sicher;

	/** Mindestlevel der Gegner */

	private int minLvlGegner;

	/** Maximallevel der Gegner*/

	private int maxLvlGegner;

	/** Die Items in diesem Raum */

	private ArrayList<Item> itemliste;

	/**

	 * 

	 * @param name

	 *            Name des Raumes

	 * @param beschreibung

	 *            Die Beschreibung des Raumes

	 * @param minLvl

	 *            Das minimum Level der vorhandenen Gegner

	 * @param maxLvl

	 *            Das maximal Level der vorhandenen Gegner

	 * @param sicher

	 *            Ob der Raum sicher ist. Sicher ist der Raum, wenn keine 

	 *            Gegner vorhanden sind

	 * 

	 *            Dieser erstellte Raum hat noch keine Ausgaenge. Diese muessen

	 *            nachtragelich hinzugefuegt werden.

	 */

	public Raum(String name, String beschreibung, int minLvl, int maxLvl, boolean sicher) {

		this.beschreibung = beschreibung;

		this.name = name;

		this.minLvlGegner = minLvl;

		this.maxLvlGegner = maxLvl;

		this.sicher = sicher;

		ausgaenge = new ArrayList<Ausgang>();

		gegnerliste = new ArrayList<Gegner>();

		itemliste = new ArrayList<Item>();

	}



	/**

	 * 

	 * @param ausgang

	 *            Ausgang der hinzugefuegt wird

	 */

	public void fuegeAusgangHinzu(Ausgang ausgang) {

		if (!ausgaenge.contains(ausgang)) {

			ausgaenge.add(ausgang);

		}

	}



	/**

	 * 

	 * @param ausgang

	 *            Ausgang der geloescht wird

	 */

	public void loescheAusgang(Ausgang ausgang) {

		if (ausgaenge.contains(ausgang)) {

			ausgaenge.remove(ausgang);

		}

	}



	/**

	 * 

	 * @param gegner

	 *            Gegner der der Liste hinzugefuegt wird

	 */

	public void fuegeGegnerHinzu(Gegner gegner) {

		if (!gegnerliste.contains(gegner)) {

			gegnerliste.add(gegner);

		}

	}



	/**

	 * 

	 * @param gegner

	 *            Gegner der geloescht wird

	 */

	public void loescheGegner(Gegner gegner) {

		if (gegnerliste.contains(gegner)) {

			gegnerliste.remove(gegner);

		}

	}

	

	/**

	 * 

	 * @param item Item, welches hinzugefuegt wird

	 * 

	 * Fuegt ein Item der Liste hinzu.

	 */

	public void fuegeItemHinzu(Item item){

		if(!itemliste.contains(item)){

			itemliste.add(item);

		}

	}

	

	/**

	 * 

	 * @param item Item, welches geloescht werden soll.

	 */

	public void loescheItem(Item item){

		if(itemliste.contains(item)){

			itemliste.remove(item);

		}

	}



	/**

	 * 

	 * @return Ein Text der den Raum beschreibt inklusive des Namen

	 */

	public String erstelleRaumText() {

		String s = name + "\n\n" + beschreibung + "\n\n";

		s += erstelleGegnerText();

		return s;

	}



	public String erstelleGegnerText(){

		String s = "";

		if(!isSicher() && gegnerliste.size() > 0){

			s += "Der Raum scheint dir unsicher zu sein und als du dich umsiehst" +

					" erblickst du auch gleich: ";

			Gegner g = null;

			for(int i = 0; i < gegnerliste.size(); i++){

				g = gegnerliste.get(i);

				s += "\n" + g.getName() + " (" + (i + 1) + ")";

			}

		}else if(!isSicher()){ //Raum nicht sicher, aber keine Monster vorhanden

			s += "Der Raum scheint unsicher, aber du kannst keine Monster erblicken.\n" +

					"Sei dennoch bist du vorsichtig.";

		}else{ //Raum ist sicher

			s += "Dieser Raum scheint sicher und du kannst beruhigt eine Pause machen" +

					" und dich in Ruhe umschauen.";

		}

		

		s += "\n";

		return s;

	}

	

	/**

	 * 

	 * @return Alle Ausgaenge in Textform

	 */

	public String erstelleAusgaengeText() {

		String s = "Vorhandene Wege in den Richtungen:\n";

		for (int i = 0; i < ausgaenge.size(); i++) {

			Ausgang a = ausgaenge.get(i);

			s += a.getRichtungName() + " / " + a.getKurzRichungName() + "\n";

		}

		

		return s;

	}

	

	public String erstelleItemsText(){

		String s = "Du siehst dich hier um und entdeckst:\n";

		String tmp = "";

		for(int i = 0; i < itemliste.size(); i++){

			Item item = itemliste.get(i);

			tmp += "\n" + item.getName() + " (" + (i + 1) + ")";

		}

		if(tmp.length() == 0){

			s += "\nLeider kannst du nichts entdecken.";

		}else{

			s += tmp;

		}

		s += "\n\n";

		

		return s;

	}

	

	public boolean isSicher(){

		return sicher;

	}

	

	public int getMinLvlGegner(){

		return minLvlGegner;

	}

	

	public int getMaxLvlGegner(){

		return maxLvlGegner;

	}

	

	public int getGegnerAnzahl(){

		return gegnerliste.size();

	}



	@SuppressWarnings("unchecked")

	public ArrayList<Ausgang> getAusgaenge() {

		return (ArrayList<Ausgang>) ausgaenge.clone();

	}



	@SuppressWarnings("unchecked")

	public ArrayList<Gegner> getGegnerliste() {

		return (ArrayList<Gegner>) gegnerliste.clone();

	}

	

	@SuppressWarnings("unchecked")

	public ArrayList<Item> getItemliste() {

		return (ArrayList<Item>) itemliste.clone();

	}

	

	public String getBeschreibung() {

		return beschreibung;

	}



	public String getName() {

		return name;

	}

}
```

Ich entschuldige mich vorsichtshalber mal für Unübersichtlichkeit in meinem Code 
Das Probelm ist für mich, dass ich momentan für jeden Raum den ich benutze in der Logik Klasse einen Raum anlege, also quasi per Hand und für den, dann noch jeweils die Gegner/Items. Die Gegner liessen sich eventuell noch automatisieren (Dafür gbts ansich schon ein paar Variablen), aber darüber hab ich mir noch nicht genauer Gedanken gemacht, weil der Rest mir noch nicht klar ist. Also wie ich den möglichst einfach halten kann und auch ohne es direkt in den Code schreiben zu müssen, damit es leichter erweiter und auch wiederverwendbar.

Wenn ich Unfug schreibe oder nicht deutlich genug erkläre sagts mir einfach... Ich hab manchmal damit Probleme es richtig zu erklären ^^.

Gruß Mofi


----------



## Marco13 (29. Nov 2011)

Ja... die Klasse ist... nicht direkt "klasse"  aber... geht es nun um ein Dateiformat oder was...?!


----------



## Mofi (29. Nov 2011)

Marco13 hat gesagt.:


> Ja... die Klasse ist... nicht direkt "klasse"  aber... geht es nun um ein Dateiformat oder was...?!



Das meine Klasse mal überholt werden müssten ist mir klar  Ich kann es nur nicht wirklich besser.

Nun Dateiformat. Ja irgendwie schon. Das Problem ist nur, dass ich nicht weiß wie man das sinnvoll umsetzt. Bzw wie ich die Daten sinnvoll irgendwo reinschreibe, dass das Programm alle Daten hat die es braucht (sind ein paar) und der der die Dateien schreibt auch weiß wie er es schreibt ohne den Überblick zu verlieren.

Ich würde euch nur sehr ungern die anderen Klassen antun  Aber um es zu verdeutlichen:
Bisher gibt es als Items nur "Nahrung" Und um davon ein Objekt zu erschaffen muss man dem Konstruktor zwei Sachen übergeben, den Namen und wie viele Lebenspunkte man wiederbekommt. Den Rest (dazu gehört noch ein wenig mehr, was aber an meinem verqueren Code liegt) macht die Klasse selbst, da der Rest für alle Nahrungsmittel gleich sein soll.
Das wäre vllt noch relativ einfach (wenn man weiß wie :autsch: Hab nie was mit XML gemacht)
Aber um einen Gegner zu erstellen braucht man mehr. Einiges mehr.
Wenn ich euch da den Konstruktor posten würde, müsste ich gut 4 - 6 andere mitposten 
Aber in Kurzform braucht ein Gegner:
Level
Lebenspunkte
Geldbestand (Gold, Silber, Kupfer)
Waffen
Rüstungen ( 6 - 7 sind möglich)
Attribute (Stärke und sowas, für Angriff)
Name

Und für Waffe + Rüstung muss man wieder mehrere Sachen angeben (Geschwindigkeit, Schaden, und so weiter)

Spätestens ab da (eigentlich vorher) versagt mein Gehirn, wie man das möglichst sinnvoll irgendwo abspeichert.

Du hattest weiter oben ein Stück XML gepostet...Ich kenn mich damit nicht aus, aber wäre es rein theoretisch möglich sowas komplexes aufzubauen?

Vielleicht hab ich allgemein alles zu komplex aufgebaut  Ich glaub ich hab mich irgendwo grad verwirrt.

Um deine Frage mal zu beantworten. Im Endeffekt wird es wohl auf ein Dateiformat rauslaufen. Da mir bisher nichts besseres eingefallen ist um Sachen außerhalb des Codes "aufzubauen". Aber bei so vielen verschiedenen Sachen/Variablen die bedacht/befüllt werden müssen, ist mir nie eine Struktur eingefallen, die man leicht umsetzen könnte. Da man sowas ja auch noch in ein paar Wochen möglichst verstehen sollte ohne sehr lange forschen zu müssen, was man sich damals dabei gedacht hatte.

Und dadurch, dass ich auch erst am Anfang stehe und noch einiges hinzu kommt besteht immer die Gefahr, dass die Klasse so nicht fertig sind (zumindestens bei einigen Klassen besteht die Gefahr - nicht bei allen). Also muss die Struktur unter Umständen auch erweiterbar sein.

Ich hatte mir mal überlegt extra Dateien für Räume anzulegen, extra Dateien für Gegner, welche für Items etc. Aber 1. schien es mir immer zu umtändlich und 2. müsste man die irgendwie wieder verknüpfen...

Falls ich euch jetzt mitverwirrt hab tuts mir leid . Aber ich denk leider immer etwas quer und verwirrend für andere ^^

(Btw falls wirklich Interesse besteht ein paar Klassen zu sehen [als Beispiel wie man es vllt nicht machen sollte ] dann sagt Bescheid, dann bearbeit ich sie noch halbwegs verständlich, weiß nur nicht wie wichtig die ganzen Dinge sind um eine Struktur zu überlegen)

Gruß Mofi


----------



## Marco13 (30. Nov 2011)

Ja, grob ist wohl rübergekommen, was gemeint ist. Die Möglichkeiten, sowas zu speichern, reichen von einer Datenbank über XML (mit automatischer Umwandlung im Beans-Stil oder Dingen wie CASTOR oder so) über manuell bearbeitetes XML (kann frickelig sein) bis hin zu eigenen Dateiformaten oder schlicht serialisierten Objekten. Welches davon das einfachste/angemessenste ist, kann ich spontan nicht sagen (hatte bisher praktisch nur mit handgefrickeltem XML zu tun  ). Vielleicht hat noch jemand anderes einen konkreteren Tipp...


----------

