Dies ist eine Designfrage ... Ich bin sicher, dass dies allgemeiner sein könnte, aber ich habe es schwer damit. Ich wundere mich über Design für Spielobjekt-Interaktionen - hier ist mein Beispiel (2D-Puzzle-Plattform).
Angenommen, der Spieler versucht, ein Level zu überwinden. Es gibt viele Lichter, die in verschiedene Richtungen gerichtet werden können. Hier ist ein Beispiel, wie diese Lichtobjekte interagieren könnten ...
- One Light projiziert eine Plattform, mit der der Spieler eine Lücke überqueren kann
- Ein Licht verringert die Reibungskoeffizienten von allem, was es berührt, ein anderes erhöht sie
- Ein Licht hebt die Effekte aller Lichter auf, wodurch die Plattform verschwindet, während dieses Licht eingeschaltet ist, und hebt die Reibungsmodifikatoren auf
- Etc...
Wie kann dieses Problem am besten gelöst werden, wenn eine Komponentenarchitektur verwendet wird? Komponenten für jedes Hauptobjekt sind offensichtlich und bieten eine saubere Möglichkeit, ihre Auswirkungen auf die Umwelt zu definieren. Eine Klasse, um Interaktion "aufzulösen" (scheint, als könnte das schnell zu einem Chaos werden)? Verwenden Sie das Dekorationsmuster, um kombinierte Objekte für diejenigen zu erstellen, die zu einem bestimmten Zeitpunkt interagieren? Eine Datenstruktur, die sich dazu anbietet?
Auch das Anschließen von Audio an diese Interaktionen? Das Anschließen von Audio an das System scheint genauso zu sein wie das Anschließen einer anderen Eigenschaft, z. B. der Sichtbarkeit oder der Bewegung / Kollision des Players.
Wenn weitere Komponenten hinzugefügt werden, wäre es natürlich schön, wenn es ein robustes System gäbe, das neue mit nur geringen Änderungen handhaben könnte, aber ich bin nicht mit der Vorgehensweise beim Entwerfen vertraut.
Sonstige Informationen: Die von mir verwendete Engine ist eine XNA-Engine namens IceCream .
quelle
Antworten:
In einem objektorientierten System besteht die einzig richtige Antwort auf die Frage , wie X am besten funktioniert, darin, dass Sie es auf die einfachste Art und Weise tun, die Sie sich vorstellen können, um etwas zum Laufen zu bringen und es dann bei Bedarf zu ändern der leichtere Ausdruck wird deutlich. Sich mit der Auswahl des richtigen Musters zu befassen, bevor Sie Code geschrieben haben, ist eine gute Möglichkeit, sich von Anfang an mit der falschen Antwort zu satteln. Lassen Sie alle Gedanken an Muster und Komponenten verschwinden und folgen Sie einfach diesen Schritten, beginnend von Ihrem heutigen Standort aus (vorausgesetzt, Sie haben eine leichte Komponente implementiert):
Zu diesem Zeitpunkt werden Sie (wahrscheinlich) eine Menge duplizierten Codes haben. Extrahieren Sie allgemeinen Code in Funktionen oder eine andere Klasse (möglicherweise eine Basisklasse) oder was auch immer angemessen erscheint. Nur weil Sie mit einer "Lichtkomponente" begonnen haben, heißt das noch lange nicht, dass LightComponent eine geeignete Basis ist. Es kann sein, dass der Code, aus dem sich die Lichtkomponente zusammensetzt, nicht wirklich eine "Komponente" an sich ist und dass dies möglicherweise am besten durch eine Reihe von Funktionen oder sogar eine separate Klasse dargestellt wird, die in Ihre neuen Komponenten aggregiert wird (als Mitgliedsvariable) ).
quelle
Wenn ein Objekt vom Typ A mit einem Objekt vom Typ B interagiert, möchten Sie im Allgemeinen einen gewissen Effekt C erzielen. Dies wird als "doppelter Versand" bezeichnet und ist in C-ähnlichen Sprachen nur sehr schwer elegant möglich.
Der effektive, aber schwer zu wartende Weg ist nur ein Haufen von Schalter- und if-Anweisungen, abhängig von den Arten Ihrer Objekte. Sie werden sich schmutzig fühlen, wenn Sie es schreiben, aber es wird die Arbeit erledigen.
Das Besuchermuster ist eine robustere Lösung, die das lästige Wechseln verbirgt, deren Einrichtung jedoch umständlich sein kann.
Normalerweise ist jede Art von Typumschaltung in Ihrem Code ein Geruch, aber hier versuchen Sie, den Polymorphismus zu verallgemeinern, der normalerweise Funktionen basierend auf einem einzelnen Typ umschaltet, um Funktionen basierend auf zwei Typen umzuschalten. Polymorphismus ist eine Grundlage von OOP, es ist also kein Geruch.
quelle
Lass mich sehen. Dies ist nur etwas, das ich mir beim Schreiben ausgedacht habe. Es tut mir leid, wenn ich etwas verpasse.
Holen Sie sich alle Lichtknoten in einem angemessenen Abstand um Ihren Kumpel.
Für jedes Licht, das Sie rendern, wird ein Polygon, das den Wirkungsbereich darstellt, auf ein Framebuffer-Objekt gerendert. Ein Lichtkegel würde also einen Kegel einer Pixelart in Ihrem FBO erzeugen. Rendern Sie jeden Knotentyp in Übergängen mit der entsprechenden Priorität. Sie könnten Informationen in jedes Pixel kodieren, so wie der grüne Kanal Reibung sein könnte, Rot Schwerkraft, Blau und Alpha etwas anderes.
Durchdachte Farbmischtechniken könnten dann interessante Effekte erzeugen. Jedes Level kann seine eigenen Mischregeln haben. Sie können auch Fragment-Shading für psychedelische dynamische Effekte wie pulsierende Schwerkraft usw. hinzufügen.
Zuletzt überprüfen Sie einfach, welche Pixel Ihr Mandude berührt, und führen Sie eine Neuberechnung der Bitmap durch, wenn Sie sich den Rändern des vorberechneten Bereichs nähern.
Eine grobe Skizze, die in 2 Minuten erstellt wurde, um meine Idee zu veranschaulichen:
Bearbeiten: In der Praxis bedeutet dies, dass Sie nur eine Lichtkomponente benötigen, die eine bestimmte Farbe ausstrahlt. Die Regeln, die damit verbunden sind, welche Farbe was macht, können ganz woanders sein. Sie können viele Daten in die 32 Bit codieren, die Sie für ein Pixel haben. Alternativ können Sie mehrere FBOs mit unterschiedlichen Attributen haben, die sich nicht gegenseitig beeinflussen. Sie könnten einen Schwerkraft- / Reibungs-FBO und einen 1-Bit-Kollisions-FBO haben. Wenn Sie dies wählen, müssen Sie natürlich markieren, in welches FBO Ihr Licht gerendert werden soll.
quelle
Das Beobachtermuster ist eine der besten Lösungen. Die Nachricht wird nur an die Objekte (Komponenten) gesendet, die wirklich daran interessiert sind. Der Empfänger muss diesen Nachrichten- / Ereignistyp abonnieren.
Es gibt viele Signal / Slot-Implementierungen. In C ++ gibt es beispielsweise eine Sigslot-Bibliothek
Weitere Informationen finden Sie unter Qt-Signale und -Slots .
quelle