Kommunikation zwischen Spieler und seinen "Objekten&quo

Übersicht Sonstiges Smalltalk

Neue Antwort erstellen

M0rgenstern

Betreff: Kommunikation zwischen Spieler und seinen "Objekten&quo

BeitragMo, Okt 10, 2011 9:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Leute,
Ich bin momentan dabei ein Projekt mit C# zu programmieren.
Momentan bin ich noch zum Teil in der Planung der Klassen und mir stellt sich jetzt eine Designfrage.
Das Problem ist, dass ich das Gefühl habe ein wenig festgefahren zu sein in meinem Denkmuster und weiß deshalb nicht genau, welchen der beiden Ansätze, die ich mir ausgedacht habe, ich verfolgen soll.

Das ganze sieht folgendermaßen aus:
Ich möchte eine Playerklasse haben, die Felder wie "CurrentKeyboardState" und "PreviouskeyboardState" hat, so dass ich die Tastendrücke über den Spieler selbst verwalten kann. Das ist schon eine Vorbereitung darauf die Klasse später weiterzuverwenden und die Tastenbelegung wählbar zu machen.
Bei diesem Projekt soll das nun so sein: Der Spieler hat eine "Drohne", also ein Spielobjekt das er steuert.
Diese Drohne hat eine Methode um sich zu bewegen. Innerhalb dieser Methode wird dann überprüft ob die entsprechenden Tasten auf der Tastatur gedrückt werden, und dann wird die Drohne in die entsprechende Richtung bewegt.
Das Klassendiagramm dazu würde so aussehen:
user posted image

Hier müsste der Spieler eine Drohne haben und die Drohne müsste den Spieler kennen, bzw wie im Diagramm zu sehen, einen "Owner" haben.

Die zweite Möglichkeit die mir eingefallen ist, ist diese:
Die Drohne bietet ein paar Methoden für die Bewegung an. Innerhalb der Spielerklasse wird dann überprüft, welche Tasten gedrückt wurden und entsprechend werden dann die Methoden der Drohne aufgerufen.

Bei der 1. Version sehe ich einfach das Problem, dass es redundant sein könnte, dass beide Klassen gegenseitig auf sich zugreifen.

Bei der 2. Version sehe ich das Problem, dass das ganze nicht so dynamisch ist, also dass es zu sehr von der Spielerklasse abhängt, was mit den Tastendrücken passiert, obwohl die Drohnenklasse eigentlich besser wissen könnte, was sie alles machen kann.

Kann mir vielleicht jemand helfen und mir bitte sagen, welche der beiden Versionen (seiner Meinung nach) besser ist und warum. Oder: Wenn es einen anderen/besseren Ansatz gibt, wie sähe dieser dann aus?
Ich habs in letzter Zeit immer nach Version 1 gemacht und hatte öfter mal Probleme bei der Initialisation.

Lg, M0rgenstern

ChaosCoder

BeitragMo, Okt 10, 2011 12:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich würde die zweite Variante bevorzugen.

Man stelle sich vor, du möchtest eine KI integrieren oder ein Netzwerkspiel daraus machen.
So kann die Drohne existieren, ohne zu wissen, wie die Eingabe vonstatten geht. Das kann also ein Spieler mit einer Maus sein, einer Tastatur, ein Playerobjekt, das über einen Internetport auf mögliche Eingaben reagiert, oder eben eine künstliche Intelligenz, die gar keine Benutzereingabe erhält.

Man sieht also deutlich, dass die zweite Variante viel flexibler und allgemeiner gehalten ist. Aus diesem Grund kann ich dir also nur dazu raten. Smile
Projekte: Geolaria | aNemy
Webseite: chaosspace.de

M0rgenstern

BeitragMo, Okt 10, 2011 13:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Okay, wenn mans so betrachtet ist die zweite Möglichkeit eindeutig flexibler.
Werde das dann auch so machen, vielen Dank.
Wie gesagt, in letzter Zeit hab ichs immer nahc Version 1 gemacht aber es kam mir komisch vor.

Lg, m0rgenstern
 

MasterK

BeitragMo, Okt 10, 2011 23:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Man sollte beachten, dass die drohne der abstrakten player-Klasse bekannt ist, während die abstrakte player-klasse keine keyboard states hat. Denn wenn du jetzt wirklich wie von ChaosCoder vorgeschlagen zB einen "MousePlayer" hast, dann wäre es natürlich dumm wenn du keyboardstates in der abstrakten playerklasse hast. Und genauso ungünstig ist es dann natürlich auch, wenn die drohne nur von der spezialisierten player-klasse gesteuert wird.
Genau genommen müsste man das input-handling dann aber auch in eine seperate klasse auslagern. Also in etwa so:

Code: [AUSKLAPPEN]

Drohne <-- Abstractplayer <-- LocalPlayer --> Mouse-Input
                    ^                |---> Keyboard-Input
                    |
                    |---- Networkplayer
                    |---- KI Player


Ich hoffe, mein grafik-meisterwerk ist zu erkennen Smile
+++ www.masterk.de.vu +++
Lila FTW!

M0rgenstern

BeitragMo, Okt 10, 2011 23:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, zuersteinmal: Es wird gar nicht möglich sein, das Spiel nur mit der Maus zu spielen, also hat sich das schon erledigt.
Außerdem glaube ich, hast du dir das Diagramm ein wenig falsch angeschaut:
Die abstrakte Playerklasse kennt keine Drohne, hat aber die Keyboardstates.
Außerdem kann die Drohne nur von der, wie du sagst "spezialisierten" Spielerklasse gesteuert werden. Das liegt in der Natur von Klassen, die abstrakte Klassen implementieren. Man kann die abstrakte Playerklasse ja nicht instanziieren, das ist verboten.

So wie ChaosCoder es vorgeschalgen hat ist es wunderbar: Die Drohne stellt Methoden für andere Klassen zur Verfügung und entscheidet was in diesen Methoden gemacht wird. Die anderen Klassen entscheiden, unter welchen Umständen welche Methode aufgerufen wird.
Beispiel: Der Spieler drückt auf seiner Tastatur die Pfeiltaste nach oben - die Drohne bewegt sich vorwärts, da dabei die Methode "MoveForward" der Drohne aufgerufen wird.
Der KI-Spieler hingegen braucht keinen Tastendruck und ruft die Methode einfach auf.

Das ganze sieht also jetzt so aus:
user posted image

Uploaded with ImageShack.us

Ich kann also ehrlich gesagt deine Einwände nicht nachvollziehen, vielleicht kannst dus ein bisschen besser erklären, was dich stört?

lg, M0rgenstern

Jolinah

BeitragDi, Okt 11, 2011 0:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Er meinte vermutlich folgendes: Wenn du mehrere spezialisierte Playerklassen hättest, und jede dieser Klassen die Aufgabe hat, eine Drohne zu steuern, dann würde es mehr Sinn machen diese Drohne direkt in der abstrakten Klasse zu verknüpfen. Ansonsten müsstest du ja die Drone-Eigenschaft bei jeder spezialisierten Klasse neu einfügen.

Und gleichzeitig würde ja nicht jede dieser spezialisierten Klassen die Tastatureingabe benötigen (ein KI-Player z.B. benötigt keine Eingabe). Das heisst diese würde man dann eher aus der abstrakten Klasse rausnehmen und in die spezialisierte Klasse einfügen welche wirklich die Tastatureingabe benötigt.

Falls es aber sowieso nur einen Typ von Player gibt, ist eine abstrakte Klasse eigentlich gar nicht nötig. Wenn es nur um Erweiterbarkeit geht, dann treffen aber die Aussagen von vorher bereits wieder zu, da diese Massnahmen die Erweiterbarkeit verbessern könnten.

Aber schlussendlich muss das ja schon aufs Programm zugeschnitten sein, man sollte auch nicht zu sehr abstrahieren, da das viel Zeit kosten kann Wink
 

MasterK

BeitragDi, Okt 11, 2011 19:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke Jolinah, dem ist eigentlich nichts mehr hinzuzufügen Smile

Ich denke beim softwaredesign gern ein paar iterationszyklen voraus. Wenn man das ein paar jahre lang beruflich macht, dann kommt das automatisch. Unangenehmer nebeneffekt ist dann häufig, dass man mit kanonen auf spatzen schiesst. Aber dafür sinds softwaretechnisch tolle kanonen Smile

Dein jetztiges konzept ist besser als das vorherige, du ziehst dabei aber immer noch recht wenig vorteile aus der OOP.
+++ www.masterk.de.vu +++
Lila FTW!

M0rgenstern

BeitragDi, Okt 11, 2011 19:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich denke da Projektübergreifend:
Ich erstelle ein paar Klassen, die ich unabhängig vom jetzigen Projekt in jedem anderen genauso weiterverwenden kann.
Deshalb die abstrakte Spielerklasse, die auch die Drohne nicht kennt: Die Drohne ist nicht unbedingt in jedem zukünftigen Projekt ein Spielobjekt.
Die KI bekommt (wenn es soweit ist) eine eigene Klasse, die nichts mit dem Spieler zu tun hat.

@MasterK:
Wie könnte ich denn noch mehr Vorteile aus der OOP ziehen, jetztmal bezogen auf die Klassen auf dem Bild?

Lg, M0rgenstern
 

MasterK

BeitragMi, Okt 12, 2011 22:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Nun, du machst einige klassische anfängerfehler was OOP angeht. Ist jetzt nicht böse gemeint, kein meister ist vom himmel gefallen. Wobei "fehler" vielleicht nicht das richtige wort ist, aber es geht eben durchaus besser.

Zum teil ist das kein objektorientiertes design, du teilst den code nur in module auf. Dazu braucht man keine OOP sprache, das geht auch mit QB und C.

Echte wiederverwendbarkeit ergibt sich darum bei vielen klassen nicht. Sicher, du kannst PlayerAbstract wahrscheinlich in vielen anderen spielen wiederverwenden, aber was steckt da schon gross drin? Letztendlich kannst du nur ein paar utility klassen in anderen projekten verwenden. Das geht aber wie gesagt auch problemlos ohne OOP.

Was man konkret an deinem beispiel verbessern könnte, wenn man aus OOP mehr nutzen ziehen will:

1) Der player
Das hatte ich ja schon angesprochen. Es wäre ein leichtes zB einen KI-spieler oder einen netzwerk-spieler zu erzeugen wenn mehr logik in den abstract-player ausgelagert wird. In der jetzigen aufteilung müsstest du zB für den netzwerk-spieler eine komplett neue Player klasse schreiben. Wenn hingegen der abstrakte player für die steuerung der drohne zuständig ist, kann der konkrete player die KI oder ein netzwerk-spieler sein.

2) Input
Der player kennt die tastatur, das ist schlecht. Ok, dein spiel ist nicht mit maus steuerbar, aber evtl mit gamepad? Besser wäre es, wenn der player nur das input-interface kennt. Dann können beliebige input-devices verwendet werden.

3) Die drohne
Der player kennt die drohne direkt. Auch hier wäre eine abstrahierung sinnvoll. Vielleicht willst du mal eine "anti-drohne" hinzufügen die von anderen spielern gesteuert werden kann. Daher sollten die player nur ein halbwegs abstraktes gameobjekt kennen (zu sehr übertreiben natürlich nicht). Es muss kein "GameEntity" sein, aber zB ein "AbstractPlayerObject", was von GameEntity erbt.

4) Grafik
Sowohl player als auch drohne scheinen selbst für das zeichnen verantwortlich zu sein, zumindest haben sie einige entsprechende methoden. So ein gameobjekt sollte am besten nur ein abstraktes grafik-objekt bekommen (zB ein Sprite), dieses aber nie selbst zeichnen. Das ist aufgabe eine grafik-"engine" (eine klasse die alle grafik-objekte kennt und beim redraw alles zeichnet was gezeichnet werden muss).

Ganz allgemein kann man auch noch sagen, dass deine abstrakten klassen so keinen sinn machen, da sie von niemanden verwendet werden. Eines der wichtigsten OOP-gedanken ist es, immer wenn möglich gegen interfaces oder höchstens abstrakte klassen zu programmieren. Bei dir hingegen wird immer auf die konkrete implementierung zugegriffen, die abstrakten klassen dahinter sind nur "stubs", sonst nix. Das ist nicht das, was man damit erreichen will wenn man objektorientiert entwickelt.

Wie schon gesagt, dass kann natürlich alles overkill werden, vor allem für kleinere projekte. Aber wenn man sich gedanken zum objektdesign macht, dann sollte man ruhig auch etwas mehr in die tiefe gehen und schauen was sinnvoll ist.

Und dazu kommt, dass dein objektmodell ja nur einen kleinen ausschnitt darstellt Viel kann man damit ja noch nicht machen, wahrscheinlich nur eine drohne übers spielfeld scheuchen. Mit mehr objekten bzw klassen ergeben sich mit brauchbarer abstrahierung wahrscheinlich noch etliche andere sinnvolle verbesserungen.
+++ www.masterk.de.vu +++
Lila FTW!

M0rgenstern

BeitragFr, Okt 14, 2011 12:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey MasterK,
Vielen Dank für die vielen Tipps.

Das mit dem Input-Interface ist eine super Idee. Die Steuerung für Maus und Tastatur habe ich schon umgesetzt, das ganze in ein Input-Interface zu packen wäre super, da muss ich nur mal sehen wie genau das umzusetzen ist. Dann würde das auch viel mehr Sinn machen das ganze in den Abstrakt-Player zu packen.
Wenn ich dann noch ein "PlayerObject" einfüge und die Drohne davon ableite, dann wäre das auch sehr sinnvoll dieses Objekt in den abstrakten Spieler einzufügen.
Ich werde das nochmal überarbeiten und dabei deine Tipps beachten. Wenn man jahrelang mit ner Sprache arbeitet, die nur OOP Ansätze hat und dann mit einer Sprache arbeitet, die komplett objektorientiert ist, dann muss man sich erst umgewöhnen. Deshalb ist es gut, wenn jemand auf Fehler hinweist.

Wegen der Grafik:
Ja und Nein. Der Spieler wird gar nicht gezeichnet, er ruft in dieser Methode nur die Draw Methode für seine Drohne auf. Und auch die Drohne zeichnet sich nicht direkt selber. Sie hat ein "IngameImage", das alle nötigen Informationen zum Zeichnen besitzt. In der Draw Methode der Drohne wird dann nur die Draw Methode des Bildes aufgerufen.

Lg, M0rgenstern
 

MasterK

BeitragFr, Okt 14, 2011 19:55
Antworten mit Zitat
Benutzer-Profile anzeigen
@Grafik:

Aha, ok. Dennoch wäre es, wenn man stärker abstrahieren möchte, sinnvoll, nicht bei jedem draw dem player zu sagen, dass er der drohne sagen soll, dass sie dem IngameImage sagen soll, dass es sich neu zeichnet. Wenn man mehr abstrahieren möchte, dann geht man beispielsweise so an die sache ran, dass man dem IngameImage nur sagt: "Ab jetzt zeichnest du dich an position X,Y mit rotation Z". Das tatsächliche zeichnen aller Grafikobjekte soll dann eine andere spezialisierte klasse übernehmen. Also das aufrufen der draw()-Methode sollten nicht player oder drohne übernehmen.


Zugegeben, wenn ich einfach mal ein kleines spiel in ein paar wochen entwickle, dann beachte ich das alles auch nicht weiter. In der regel ist das dann häufig "fire and forget". Der code ist für das eine spiel da und mehr nicht.
+++ www.masterk.de.vu +++
Lila FTW!

Neue Antwort erstellen


Übersicht Sonstiges Smalltalk

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group