# Selber aktualisierendes JPane für RPG



## Macki (8. Aug 2006)

Hallo zusammen,

habe da mal eine Frage zu meinem u.g. Code. Wie man sieht progge ich gerade ein RPG und versuche nun dem Helden einen (spätere mehrere) Verbündete zuzuweisen.

Dazu soll der Held den Verbündeten auf den er trifft (wird per Zufall ausgelost=verbart) dreimal ansprechen müssen. Jedes dieser drei Male hat er die Wahlmöglichkeit zwischen einer "lieben", einer "neutralen" und einer "aggressiven" Ansprache, auf die der mögliche Verbündete unterschiedlich reagieren soll. Da ich nun aber 26 mögliche Verbündete in mein Spiel integrieren will (hier nur 6 aufgeführt) weiß ich nicht ganz genau, wie ich dieses "Frage-Antwort-Spiel" am besten implementiere.

Mir fällt nur ein, jedem Verbündeten jeweils 3x3 eigene Buttons zu geben und dann mittels Actionevent jedesmal das gleich Bild(Pane) wieder aufzurufen um dann am Ende zu fragen, soll er (der Verbündete) dich begleiten.

Nach jedem Knopfdruck soll aber ein Label erscheinen, dass die Antwort des Verbündeten auf die Anrede enthalten soll. wie zum Beispiel "Er ist nicht begeistert", etc.

ist es nicht möglich so etwas wie (achtung nun Pseudo-Code)

if (freundlich gedrückt) {
pic1.add(Label ...)
else if (neutral gedrückt){
pic1.add(Label ....)

usw. zu machen, damit sich das Pane immer selber aktualisiert wenn ein Knopf gedrückt worden ist?

Wenn das nicht geht, müsste ich bei jedem Knopfdruck das alte Panel neu öffnen, repainten und alles gleich lassen bis auf das besagte Antwort-Label hinzufügen.

Das wären dann 26x9 Actionperformed und Components...das muss doch leichter (kürzer) gehen???


```
public JComponent Verbuendeter() {
	freund.removeAll();
	freund.repaint();
	JLabel pa1;
	JLabel pa2;
	JButton weiter = new JButton("Reise fortsetzen");
	weiter.addActionListener(this);
	weiter.setActionCommand("weiter");
	weiter.setBounds(550,650,200,30);
	JButton freundlich = new JButton("freundlich ansprechen");
	freundlich.addActionListener(this);
	freundlich.setActionCommand("freundlicha");
	freundlich.setBounds(350,300,200,30);
	JButton neutral= new JButton ("neutral ansprechen");
	neutral.addActionListener(this);
	neutral.setActionCommand("neutrala");
	neutral.setBounds(350,400,200,30);
	JButton feindlich = new JButton("aggressiv ansprechen");
	feindlich.addActionListener(this);
	feindlich.setActionCommand("feindlicha");
	feindlich.setBounds(350,500,200,30);
	int verbart =6;//(int)Math.ceil(Math.random()*6);
	switch(verbart){
	case 1:
		JLabel pic1 =new JLabel(new ImageIcon("C:/Dokumente und Einstellungen/Cheffe/Eigene Dateien/Söldner Bilder/Verbündete/Simbah.jpg"));
		pa1 = new JLabel("Euer Beobachter ist ein Waldgreif");
		pa1.setBounds(150,0,1000,100);
		pa1.setFont(f);
		//pa1.setForeground(hell);
		pa2=new JLabel("Wie wollt Ihr ihn ansprechen?");
		pa2.setBounds(300,100,1000,100);
		pa2.setFont(f4);
		pic1.setLayout(null);
	    pic1.setOpaque(false);
		pic1.add(pa1);
		pic1.add(pa2);
		pic1.add(freundlich);
		pic1.add(neutral);
		pic1.add(feindlich);
		pic1.add(weiter);
		freund.add(pic1);
		break;
	case 2:
		JLabel pic2 =new JLabel(new ImageIcon("C:/Dokumente und Einstellungen/Cheffe/Eigene Dateien/Söldner Bilder/Verbündete/Emlog.jpg"));
		pa1 = new JLabel("Euer Beobachter ist ein Zentaure");
		pa1.setBounds(150,0,1000,100);
		pa1.setFont(f);
		pa2=new JLabel("Wie wollt Ihr ihn ansprechen?");
		pa2.setBounds(300,50,1000,100);
		pa2.setFont(f4);
		pa2.setForeground(hell);
		pa1.setForeground(hell);
		pic2.setLayout(null);
	    pic2.setOpaque(false);
		pic2.add(pa1);
		pic2.add(freundlich);
		pic2.add(neutral);
		pic2.add(feindlich);
		pic2.add(weiter);
		pic2.add(pa2);
		freund.add(pic2);
		break;
	case 3:
		JLabel pic3 =new JLabel(new ImageIcon("C:/Dokumente und Einstellungen/Cheffe/Eigene Dateien/Söldner Bilder/Verbündete/Nasalurk.jpg"));
		pa1 = new JLabel("Euer Beobachter ist eine junge Drachenreiterin");
		pa1.setBounds(50,0,1000,100);
		pa1.setFont(f);
		pa2=new JLabel("Wie wollt Ihr sie ansprechen?");
		pa2.setBounds(300,50,1000,100);
		pa2.setFont(f4);
		pic3.setLayout(null);
	    pic3.setOpaque(false);
		pic3.add(pa1);
		pic3.add(pa2);
		pic3.add(freundlich);
		pic3.add(neutral);
		pic3.add(feindlich);
		pic3.add(weiter);
		freund.add(pic3);
		break;
	case 4:
		JLabel pic4 =new JLabel(new ImageIcon("C:/Dokumente und Einstellungen/Cheffe/Eigene Dateien/Söldner Bilder/Verbündete/Lesara.jpg"));
		pa1 = new JLabel("Euer Beobachter ist ein Eisgreif");
		pa1.setBounds(150,0,1000,100);
		pa1.setFont(f);
		pa2=new JLabel("Wie wollt Ihr ihn ansprechen?");
		pa2.setBounds(300,50,1000,100);
		pa2.setFont(f4);
		pa2.setForeground(hell);
		pa1.setForeground(hell);
		pic4.setLayout(null);
	    pic4.setOpaque(false);
		pic4.add(pa1);
		pic4.add(pa2);
		pic4.add(freundlich);
		pic4.add(neutral);
		pic4.add(feindlich);
		pic4.add(weiter);
		freund.add(pic4);
		break;
	case 5:
		JLabel pic5 =new JLabel(new ImageIcon("C:/Dokumente und Einstellungen/Cheffe/Eigene Dateien/Söldner Bilder/Verbündete/Kubalmira.jpg"));
		pa1 = new JLabel("Euer Beobachter ist ein Chimären-Mündel");
		pa1.setBounds(150,0,1000,100);
		pa1.setFont(f);
		pa2=new JLabel("Wie wollt Ihr sie ansprechen?");
		pa2.setBounds(300,50,1000,100);
		pa2.setFont(f4);
		pa2.setForeground(hell);
		pa1.setForeground(hell);
		pic5.setLayout(null);
	    pic5.setOpaque(false);
		pic5.add(pa1);
		pic5.add(pa2);
		pic5.add(freundlich);
		pic5.add(neutral);
		pic5.add(feindlich);
		pic5.add(weiter);
		freund.add(pic5);
		break;
	case 6:
		JLabel pic6 =new JLabel(new ImageIcon("C:/Dokumente und Einstellungen/Cheffe/Eigene Dateien/Söldner Bilder/Verbündete/Kendor.jpg"));
		pa1 = new JLabel("Euer Beobachter ein Auelb");
		pa1.setBounds(250,0,1000,100);
		pa1.setFont(f);
		pa2=new JLabel("Wie wollt Ihr ihn ansprechen?");
		pa2.setBounds(350,50,1000,100);
		pa2.setFont(f4);
		pic6.setLayout(null);
	    pic6.setOpaque(false);
		pic6.add(pa1);
		pic6.add(pa2);
		pic6.add(freundlich);
		pic6.add(neutral);
		pic6.add(feindlich);
		pic6.add(weiter);
		freund.add(pic6);
		break;
	}
	return freund;
}
```

Wäre für jede Hilfe dankbar!!

Liebe Grüße
Macki


----------



## Macki (8. Aug 2006)

Sorry für's schieben, aber brauche immernoch einen Lösungsvorschlag für o.g. Problem...

Liebe Grüße
Macki


----------



## Mindstream (6. Sep 2006)

Hi,

Ich konnte das Konzept deines Spiels noch nicht erfassen. Deshalb weiß ich
 nicht, ob meine Tipps besonders geeignet sind, also musst du dir erst mal
rauspicken, was dir weiterhelfen könnte. Was soll es denn für ein 
Rollenspiel werden? Point&Click, Zelda ähnlich...?

Es kann gut sein, dass ich mich irre, aber du scheinst gar keine Struktur
(Klasse) für interne Daten zu benutzen. 

Eigentlich scheinst du ja schon den richtigen Ansatz zu haben, nur hast
 du ihn noch nicht umgesetzt.
Du hast eine Klasse Verbündeter aber diese Klasse ist nicht der Bauplan 
eines Verbündeten, sondern eine Kapselung aller Verbündeten. 
Die einzelnen Verbündeten sind nicht Objekt orientiert gestaltet, 
was zu deinem Problem führt, dass du eine switch - Anweisung benutzen musst.

Wenn ich deinen Ansatz etwas korrigiere, heißt die Klasse Verbündeter nun Verbündet*e* 
und ist ein Container ( Collection? Wrapper? ) für alle Verbündeten, 
in dem globale Instanzen für die Verbündeten angelegt werden 
(also Instanzen der Verbündeten selbst, sowie z.B. JButton freundlich). 
Dazu brauchst du allerdings noch die tatsächliche Klasse Verbündeter, 
deren Instanzen du später die individuellen Bilder übergeben kannst. 
In der Hauptmethode Verbündeter sollten alles initialisiert werden, was 
man sowieso für jede Instanz braucht (also das hinzufügen der Buttons 
neutral, freundlich, JLabel pic etc.), wodurch etwas Code wegfallen sollte. 

So im Container selbst erzeugst du dann alle Objekte der Verbündeter 
Klasse als Array damit entfällt die switch - Anweisung. 
Und du kannst mit Verbündeter[Zufallszahl] auf die einzelnen Begleiter zugreifen.

Das praktische dabei ist, dass du beim Erweitern der Verbündeter Klasse 
nicht jede case - Anweisung sondern nur eine Klasse manipulieren musst.

Ein Tipp zur Gestaltung des Spiels:
Also ich bin ein Rollenspielfan und in allen Games, 
bei denen diese Art von Dialoge verwendet wurden, 
wurde statt der Art sie anzusprechen 3 versch. konkrete Sätze vorgeschlagen, 
die man auswählen konnte.

Wenn also eine huebsche Drachenreiterin in einem Lokal sitzt fielen die Sätze etwa so aus:
- Ich komme gerade vom Volk der Drachenreitern aus dem Düsterwald 
und bin auf der Mission den Schwarzen Ritter zu bekämpfen, der die
Drachenreiter unterdrückt und terrorisiert. Die Drachenreiter sagten, du
könntest mir dabei helfen. 
- Hallo meine Süße! Kann ich dich auf einen Krug Bier einladen? 
- <Gibt ihr einen Kuss auf die Wange> und grölt mehr Bier!

Das interessante dabei war nicht nur, 
dass man bei dieser Art von Gespräch Entscheidungen traf 
und die Story auf unterschiedliche Weise vorantrieb. 
(Die Reaktion auf den letzten Satz könnte eine saftige Ohrfeige 
und den Verlust eines möglichen Gefährten sein.) 
Das besondere war auch, 
dass die Gespräche selbst Teil der Story waren
und diese (ins besondere den Charakter) ergänzten.

Noch was: 
Ein Rollenspiel ist bereits kompliziert und wird mit der Zeit immer komplizierter. 
Du solltest deinen Quelltext umbedingt besser kommentieren und dir überlegen, 
ob du eine richtige Dokumentation dazu schreiben solltest. 
Sonst verlierst du den Überblick wahrscheinlich noch bevor das Spiel überhaupt fertig ist. 
Und vermutlich willst du das Spiel auch noch später verbessern und Bugs entfernen. 
Was dir auch helfen könnte wären Flussdiagramme der einzelenen Module und Diagramme
mit den versch. Klassen und deren Interaktionen im Spiel.

cu Mindstream


----------



## Leroy42 (7. Sep 2006)

Mindstream hat gesagt.:
			
		

> Ein Rollenspiel ist bereits kompliziert und wird mit der Zeit immer komplizierter.
> Du solltest deinen Quelltext umbedingt besser kommentieren



Ich würde die (Re-)Aktionen nicht fest im Programm verdrahten, sondern
mir eine (abstrahierende) Datenstruktur ausdenken, die dann separat
aus einer Text/XML-Datei gelesen wird um das Programm variabel zu halten.


----------



## DocJunioR (7. Sep 2006)

joa, nen Markov-Baum wäre da nicht schlecht.
Eventuell kann man es aber auch ganz anders lösen, indem du dir einen Wert pro Antwort baust, der auf einen Charakterspezifischen "Vertrauenswert" einfluss hat.
Gibt der Spieler eine negative Antwort, sinkt das vertrauen, anders herum steigt es und bei neutral, naja..

Auf jeden Fall kann man dann das Frage-Antwort-Spiel so lange treiben bis das Vertrauen des Gegenüber bei +100 ist oder so und dann kommt der mit..

wenn man wie oben über ne XML gehen will, sollte das wohl so laufen:

```
<Charakter action="none"> Was denkst du jetzt zu tun?       
  <Spieler>Garnichts   
      <Charakter action="none"> Wenn du meinst 
          <Spieler ....>
           ...
      </Charakter>
  </Spieler>
  <Spieler>Na da hau ich drauf
     <Charakter action="none"> Jaaajaaaa
         ...
     </Charakter>
  </Spieler>    
</Charakter>
```

Sowas in der Art..


----------



## Mindstream (7. Sep 2006)

Hallo  



			
				Leroy42 hat gesagt.:
			
		

> Ich würde die (Re-)Aktionen nicht fest im Programm verdrahten, sondern
> mir eine (abstrahierende) Datenstruktur ausdenken, die dann separat
> aus einer Text/XML-Datei gelesen wird um das Programm variabel zu halten.



Die Umsetzung an sich finde ich gut. Aber wenn du ein größeres Frage - Antwort Spiel ähnlich dem von DocJunioR vorschlagen willst...

Falls Macki keine interne Datenverwaltung oder Struktur für interne
(nicht visuelle) Daten benutzt, ist es einfacher das Konzept bei zu halten. 
Das hinzufügen einer ungeplanten Datenstruktur und der dazugehörigen
internen Verwaltung erhöht die Komplexität und senkt die Wartungsfreundlichkeit des Programms. 
Auch wenn bereits eine eigene Datenverwaltung existiert, halte ich trotzdem die einfachen Fragen und deren Verknüpfung mit der Entscheidung ob der Gesprächspartner zum Begleiter wird für ausreichend. Diese Verknüpfung braucht auch nicht unbedingt eine externe Datenquelle, weil sie recht kurz und einfach beschaffen ist. Allerdings sehe ich bei der Benutzung einer anderen Quelle für die Fragen keine Nachteile außer dem Mehraufwand und es käme sogar einem modularen/besser zu wartenden Programm zugute. 
Ein Reaktionsspielchen ist zwar ein sehr schönes Feature, aber eben nicht mehr. Ich schlage vor zuerst das Spiel fertig zu stellen und das Feature erst dann einzubauen. Das wird vermutlich nicht viel schwerer als es momentan ist.


----------

