# Saubere Spielprogrammierung



## Sanix (25. Nov 2005)

Morgen
Wie würded ihr eine Programmierung eines Spiels angehen. Ich habe Mal ein X gewinnt programmiert, welches man übers Netzwerk spielen kann. Dabei trat vor allem das Problem auf, dass ich die Verarbeitung Anfangs in den EventListener hatte.
Also so zum Beispiel:
Oberfläche Klasse. Dort wird eine neue Klasse 4 gewinnt erstellt. An diese Klasse musste ich das JPane der Obfläche Klasse übergeben. Die Oberfläche hatte Buttons, welche natürlich einen ActionListener hatten. Dieser "empfängt" ja dann die Spielzüge, und müsste sie dann weiterleiten an die 4 Gewinnt Klasse. Also musste ich ja das 4  gewinnt objekt zuerst an diesen Listener übergeben.
Das ganze wurde dann immer komplizierter und ich musste die Objekte immer umherschieben. Mir wurde dann geraten, einen "Controller" zu machen.
Habe nicht ganz kapiert wie und schlussendlich eine Statische Klasse gemacht. Welche alle Aktione von den Listener erhalten hat und halt alle Objekte kannte, da ich sie in dieser Klasse erstellt hatte. Da sie statisch war, musste ich nicht immer Objekte hin und herschieben.
Denke aber nicht, dass dies der "saubere" Weg ist. Was gibt es hier so für Ansätze?


----------



## Lim_Dul (25. Nov 2005)

Das Problem kommt mir sehr bekannt vor.

Ich hab es so gelöst:

Gui und Spiellogik sind strikt voneiander getrennt. Gui-Elemente dürfen Objekte des Spiels nur auslesen, aber keine Daten ändern.

Die Kommunikation zwischen Gui und Spiellogik erfolgt bei mir über einen sogenannten Eventhandler.
Jede Klasse, die irgendwie auf ereignisse reagieren will, registriert sich beim zentralen Eventhandler des Spiels als Listener. Dieser Listener muss dann beim erzeugen der Gui Elemente "rumgereicht" werden - sonst eigentlich nichts.
Die Gui Elemente müssen nur wissen, auf welche Typen von Ereignissen sie reagieren müssen.

Wenn sich Beispielsweise die Punkte eines Spielers geändert haben, setzt die Spiellogik ein Event vom Typ PointsChanged ab. Das enthält den Spieler, dessen Punkte sich geändert haben und die neuen Punkte.
Das Panel, was für die Anzeige der Punkte zuständig ist, empfängt dieses Event (Alle anderen Listener ignorieren es) und ändert darauf hin seine Anzeige.

Die Spiellogik weiß nicht, wer für die Anzeige der Punkte zuständig ist. Sie weiß noch nichtmal, ob die Punkte überhaupt angezeigt werden. Sie schmeisst einfach das Event in den Eventhandler und hofft, dass sich jemand drum kümmert.
Dem Gui-Element wiederrum ist egal, wo das Ding herkommmt. Im Prinzip ist dem Gui Element sogar wurscht ob es sich um Punkte oder sonstwas handelt. Für das Gui Element ist das letztendlich nur wichtig, dass es bei Events von diesem Typ seine Darstellung aktualisieren muss.

Umgekehrt kann die Gui natürlich auch Events absetzen. Wenn beispielsweise auf eine Figur zum setzen geklickt wurde, setzt der MouseListener das Event ab, dass auf eine Figur ausgewählt wurde. Die Spiellogik empfängt dieses Event nun, nimmt daraufhin die nötigen Änderungen in den Spielobjekten vor und sendet darauf basierend neue Events was sich geändert hat.

Ich kann das ganze gerne noch was ausführlicher darstellen, aber ich denke das bietet erstmal genug Denkstoff.


----------



## simon_m (27. Nov 2005)

Das klingt sehr logisch!
Kann ich bestimmt nochmal gebrauchen!! Wie fragst du den Typ des Events ab? Das würd mich nochmal interessieren.


----------



## Lim_Dul (28. Nov 2005)

Meine Events haben alle eine Methode public int getType();
Und in der Eventklasse sind halt die Konstanten definiert, die da zurückgegeben werden können. Dann kann man einfach eine switch/case Anweisung machen und auf die passenden Events reagieren.


----------



## Newlukai (21. Dez 2005)

Lim_Dul hat gesagt.:
			
		

> Die Kommunikation zwischen Gui und Spiellogik erfolgt bei mir über einen sogenannten Eventhandler.
> Jede Klasse, die irgendwie auf ereignisse reagieren will, registriert sich beim zentralen Eventhandler des Spiels als Listener. Dieser Listener muss dann beim erzeugen der Gui Elemente "rumgereicht" werden - sonst eigentlich nichts.
> Die Gui Elemente müssen nur wissen, auf welche Typen von Ereignissen sie reagieren müssen.



Hi,

da ich im Moment selbst an einem kleinen Spiel überlege und ich mir auch schon Gedanken in diese Richtung gemacht habe, möchte ich hier nochmal nachhaken.
Beim EventHandler registrieren sich die Listener. Doch welche Methode ruft der EventHandler an den Listenern auf, wenn das entsprechende Event eintritt? Ich würde das mit einem Interface regeln, doch ich kann ja schlecht bei Swing-GUI-Elementen noch Interfaces implementieren.
Die Frage ist natürlich unnötig, wenn ich völlig auf vorgefertige GUI-Frameworks verzichte, und mein GUI selbst aufbaue.

Und wie ist das mit dem Feuern von Events. Gibt es da eine public-Methode am EventHandler á la fireEvent?

Gruß
Newlukai


----------



## Lim_Dul (21. Dez 2005)

Ich hab Interfaces dafür. Wenn ich GUI Elemente habe, die darauf reagieren müssen, leite ich da halt ab.


```
public class MyPanel extends JPanel implements MyListener
```


----------



## Newlukai (21. Dez 2005)

Lim_Dul hat gesagt.:
			
		

> leite ich da halt ab.



 :idea: Gute Idee. Das geht ja auch *g* ...


----------



## campino_nicht_eingeloggt (2. Jan 2006)

Für 3D-Spiele verwendet man eine sog. Spieleschleife...ähm...ich hatte mal ein Schaubild *such*...ah:







It is english, but it is brillaint )

Nur musst du die Events quasi "speichern", dann an der update position gucken welche inzwischen aufgetreten sind und sie bearbeiten, dafür muss der rest der Schleife natürlich schnell genug abgearbeitet werden, damit man nicht warten muss, bis der auf ein Event reagiert. Das ist für kleinere Spiele eventuell etwas aufwendig, aber bei größeren Projekten unabwendbar...

campino

PS: ich bin zu faul um mich einzuloggen...


----------



## Sanix (4. Jan 2006)

@Campino
Hast du ein Beispiel dafür?


----------



## Campino (4. Jan 2006)

Sanix hat gesagt.:
			
		

> @Campino
> Hast du ein Beispiel dafür?



Die Sache wird in ganz vielen Büchern vorgestellt, zum ersten Mal bin ich da in
"Jetzt lerne ich", "Spieleprogrammierung mit DirectX und C++" aus dem markt und Technik Verlag drauf gestossen. 

Im Internet findet sich hier http://www.mvps.org/directx/articles/writing_the_game_loop.htm was. Außerdem verwenden Spieleengines wie z.B. die JMonkeyengine (www.jmonkeyengine.com) dieses Prinzip.


----------



## Soulfly (5. Jan 2006)

Wobei das bei dem Directx-Buch schon allein von der Struktur der WinAPI gefordert wird und nicht extra geproggt werden muss. Nur so als Hinweis!

MfG
Soulfly


----------



## Campino (5. Jan 2006)

Soulfly hat gesagt.:
			
		

> Wobei das bei dem Directx-Buch schon allein von der Struktur der WinAPI gefordert wird und nicht extra geproggt werden muss. Nur so als Hinweis!
> 
> MfG
> Soulfly



Die WinAPI verwendet eine Nachrichtenschleife, diese wird von der Spielschleife weiter ausgebaut. Man kann aber auch andere Strukturen nutzen, z.B. verwendet die VM auch die Window-Nachrichtenschleife um an Events zu kommen (zumindest unter Windows, sie hat ja keine andere Chance...)


----------



## simon_m (18. Mrz 2006)

also, auch wenn das hier alles schon etwas alt ist, würde ich gerne auf LimDuls Angebot eingehen und ihn bitten, das noch etwas ausführlicher darzustllen. Ich habe es von Prinzip her verstanden nur die technische Umsetzung leuchtet mir noch nicht ganz ein (und wenn so ein Angebot schoon da steht, warum nicht fragen, bevor man sich selbst tagelang damit abrackert  )
Ich fände es glaube ich, sehr hilfreich, wenn du mal eine kleine Übersicht über deine Klassen und deren Zusammenhänge posten könntest. Dann kann man sich das alles besser vorstellen...

Also schon mal danke an Lim
mfg
zenabi


----------



## EagleEye (19. Mrz 2006)

ich bezieh das jetzt mal alles auf nen normales Prog weil ich noch keine Spiele gemacht hab
du hast halt 3 Arten:
einmal die grafische Oberfläche: Panels Labels Frames usw.
die holen sich meistens selbstständig ihre Daten die sie für die Darstellung brauchen

die 2.Art sind die Algorithmen die für die Berechnungen und so da sind diese holen sich auch die Daten und setzen diese auch wieder. Sie können auch die GUI benachrichtigen das sie einige Bereiche neu zeichnen muß dies kann man dann über Listener machen

die 3.Art sind die Daten selbst sie dienen nur als Container um Informationen zu speichern und transportieren


----------

