Du bist nicht angemeldet.

Werbeanzeige

Reth

Frischling

  • »Reth« ist der Autor dieses Themas
  • Private Nachricht senden

1

29.09.2019, 22:05

Ereignissteuerung und "Information Hiding"

Hallo zusammen,

bin mir nicht 100% sicher, ob dies das richtige Forum ist - wenn nötig bitte nach "Game-Design und Spieleentwicklung" verschieben (zwischen den beiden konnte ich mich nicht entscheiden)!

Für ein Spiel auf einem älteren System (Amiga - als Hobby) kapsele ich gerade mehr oder weniger geschickt, die Systemaufrufe (Fenster anlegen, Ereignisse verarbeiten, etc.) in C++ Klassen (außer C und C++ und ein paar anderen Sprachen wie ggf. Pascal oder Skriptsprachen steht auf dem System nicht wirklich was zur Verfügung). Das Ganze soll recht allgemein gehalten werden, damit ich es ggf. in späteren Projekten wieder verwenden kann.

Dabei hänge ich gerade an einer meiner vielen Designentscheidungen (bin echt nicht gut im Design): Es geht darum, wie allgemein z.B. Klassen für die Ereignissteuerung sein dürfen, ohne Probleme mit der Verarbeitung zu bekommen oder lauter Spezialklassen ableiten zu müssen, die dann fast "nur" Hüllen sind.

Hier mal die konkreten Beispiele: Für das Betätigen eines Buttons hab ich dessen Klasse so angelegt, dass Ereignisobjekte am Button registriert werden können. Diese haben eine einheitliche Schnittstelle "activate()", die dann einfach vom Button gerufen wird, sobald er gedrückt wurde.

Damit ich nun unterscheiden kann, welcher Button gedrückt wurde hab ich ne Spezialklasse angelegt, die dann den Typ mitbekommt, der dem Button entspricht (bei nem Spiel z.B. sowas wie "bauen", "angreifen", etc.). Bei Mausaktivitäten (bewegen, klicken, ...) läuft es ähnlich. Damit bekommt man n ziemliches Klassengeflecht, die Schnittstellen sind aber allgemein gehalten (reines activate() - es muss nichts übergeben werden).

Alles in allem stellen diese Aktivitäten aber Aktivitäten des menschlichen Spielers dar, die ich in eine Klasse packen könnte, die dann lauter spezielle Methoden bekäme (also z.B.: buttonActivate(int buttonID), mouseClicked(Point coords), usw. usf). Damit müssten aber die GUI-Elemente (inkl. Maus) immer wissen, was sie in die Methoden schieben müssten, wäre also nicht mehr so allgemein).

Beides hat Vor- und Nachteile. Was würdet ihr mir denn raten bzw. gibt es evtl. noch eine andere/bessere Variante?


Vielen Dank schon mal!

Ciao

Sacaldur

Community-Fossil

Beiträge: 2 280

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

2

30.09.2019, 10:59

Die UI-Buttons brauchen keine Spezialisierungen. Es ist egal, ob "Bauen" oder "Angreifen" drauf steht, oder ob sie sich in der Visualisierung unterscheiden (Position, Textur, ...), da das alles lediglich Eigenschaften des Buttons sind.
Falls du dich mit Button auf Tasten der Tastatur oder des Gamepads beziehst, dann solltest du tendenziell keine "Button" oder "Key" Klasse implementieren. Für Input könntest du eine Klasse "Input" implementieren, die (je nachdem was im konkreten Fall besser ist) Events für Betätigungen oder Methoden zum Abfragen des Status zur Verfügung stellt. Die Events würden dann bspw. für Mausklicks die Position beinhalten.
Schau am besten auch, wie man in C++ Callbacks umsetzen kann. So wäre es dann nur notwendig, eine Referenz auf die Funktion/Methode+Objekt zu übergeben, statt eine Klasse diese Schnittstelle implementieren zu lassen.

Andererseits solltest du schauen, dass durch das alles der Overhead nicht zu groß wird. Auf halbwegs modernen Systemen sollte das kein Problem sein, auf älteren Systemen kann das aber im schlimmsten Fall zu signifikanten Einbußen sorgen, sei es Performance oder Speicherauslastung.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Reth

Frischling

  • »Reth« ist der Autor dieses Themas
  • Private Nachricht senden

3

01.10.2019, 00:10

War vielleicht ein Missverständnis: Die Buttons sind nicht spezialisiert, sondern die Aktivitäten, welche durch sie ausgelöst werden (hat mit "Quelle des Ereignisses" zu tun - beschreib ich ein bisschen weiter unten; hab aber schon einen ersten Schritt in die Gegenrichtung gemacht - s. ebenfalls unten).

Ja, das mit dem Overhead und dem Klassenzoo ist der Punkt, der mich zu stören beginnt. Aktuell habe ich mal in einem ersten Schritt zusammen gefasst, dass es "nur" noch eine Klasse für Button-Aktivitäten gibt, dafür dann pro Button eine eigene Instanz, die im Konstruktor den Typ mit bekommt (also z.B. Gebäude, Angriff usw.).

Bei mir sind im Gegensatz zu z.B. Java die Methoden, die ich bei Eintreten von Ereignissen rufe parameterlos (Java hat in den Versionenm die ich von früher kenne Event-Objekte mitgegeben, aus denen man die Quelle des Ereignisses entnehmen konnte. Dann musste aber auch oft mit instanceof und casts gearbeitet werden). Dadurch muss die Info, woher das Ereignis kommt entweder eindeutig sein, oder anders ermittelt werden.

Wo ggf. der Klassenzoo noch etwas groß ist ist bei der Ereignisverarbeitung im Fenster. Dort habe ich ähnlich wie bei Java für verschiedene Ereignisarten unterschiedliche verarbeitende Klassen implementiert (z.B. für Mausereignisse, Button-Ereignisse usw.). Die unterscheiden sich aber aktuell kaum in den Schnittstellen (aber in der Tätigkeit). Die Klassen tun kaum was - d.h., ich könnte deren Logik auch direkt in der Fensterklasse implementieren. Dann würde diese aber wieder recht aufgebläht ... (wie man's macht ... ;) )


Callbacks kann ich mir nochmal anschauen, bin ich bisher noch kein so Fan von ...

Werbeanzeige