2009-11-05 6 views
15

vor kurzem habe ich versucht, meine Hand bei der Programmierung eines Spiels in C#. Ich benutze XNA nicht dafür, da ich dachte, ich würde mehr lernen, wenn ich das Spiel von Grund auf neu codiere (obwohl ich eine Multimedia-Engine verwende).Game Programmierung - Kommunikation zwischen Spiel-Objekten in 2d

Ich versuche ein 2D-RPG-Spiel zu entwerfen - ein bisschen ehrgeizig, weiß ich, aber ich verstehe zumindest die grundlegenden Teile des Spiels (dh den Code der "Kesselplatte") ziemlich gut und ich ' Ich habe einen Teil erreicht, von wo ich nicht weiß, wohin ich gehen soll.

Im 2D-Spiel kommen Sie durch das Spiel, indem Sie verschiedene Bereiche durchwandern. Sobald Sie auf eine "Portalkachel" treffen, werden Sie zum nächsten Bereich usw. transportiert.

Ich habe Probleme zu verstehen, wie dieses Bereichsobjekt eingerichtet werden soll. Das war meine erste Idee: Jedes Gebiet hat ein paar verschiedene Sammlungsstrukturen (zum Beispiel ein Sichtbarkeitsquadtree, ein Kollisionsquadtree, eine AI-Entity List usw.). Wenn ich also eine feindliche Entität in das Spiel einfügen würde, würde sie in den Sichtbarkeitsquadtree, den Kollisionsquadtree (weil Sie mit Entitäten kollidieren können) und die AI-Entitätsliste gesetzt werden. Wenn der Bereich eine Aktualisierungsanforderung empfängt, weist er jede dieser Strukturen an, sich selbst zu aktualisieren, was wiederum den Entitäten mitteilt, sich selbst zu aktualisieren. Alles gut, so weit.

Meine Frage ist: Was ist, wenn dieser Feind mit anderen Objekten kommunizieren muss? Zum Beispiel muss es vielleicht wissen, ob der Spieler in einem bestimmten Bereich davon war. Oder ob es vom Spieler getroffen wurde. Oder wo sich alle kollidierbaren Objekte in dem Bereich befinden (so könnte Pfad gefunden werden).

Die erste (und schlechte) Lösung für dieses Problem wäre einfach, jeder Entität einen Verweis auf jede Sammlung zu übergeben. Aber das fördert offensichtlich eng gekoppelte Objekte, was nicht gut ist.

Die zweite Lösung, die ich entwickelte, war, dass jede Entität den Bereich über Nachrichtenstrukturen abfragen konnte. So könnte ein Feind sagen: "Gebt mir eine Liste jeder Entität in X Entfernung von meiner Position" und der Bereich würde eine Antwort zurückgeben. Dies würde jedoch zunehmend schwieriger werden, da ich mehr und mehr Möglichkeiten in diesem Bereich programmieren müsste ("Gib mir eine Liste von Entitäten, die nicht in meiner Nähe sind", "Gib mir eine Liste aller Entitäten mit niedrigerer Gesundheit als X "usw.).

Was ich suche ist eine zeitgetestete Lösung für dieses Problem der Kommunikation zwischen Objekten und im Grunde, wie man einen Bereich einrichtet. Ich nehme an, es würde auch eine Art Nachrichtensystem benötigen, obwohl ich mir nicht sicher bin.

Danke fürs Lesen.

+4

Wall of Text ist beängstigend – Chad

Antwort

4

Sie könnten in die Mediator pattern suchen. Es würde Ihnen erlauben, niedrige Kopplung zu haben, aber yeah, Sie würde haben eine Menge Code in den Mediator Objekt (e), um die Kommunikation zwischen den anderen Objekten zu erleichtern. Aber ich denke, es ist entweder das eine oder das andere. Und das ist dann vorzuziehen.Es würde Ihnen auch mehr Freiheit geben, Tricks zu machen, wie bestimmte Aktualisierungsanforderungen in die Warteschlange einzureihen und die Anfragen zu geeigneteren Zeiten zu bearbeiten, oder eine Stapelverarbeitung von vielen Anfragen zu machen, statt sie einzeln zu machen, was (hypothetisch) eine Art von Anfrage würde Overhead.

4

Ich denke, die beste Option für diese Art von Dingen ist es, das Observer-Muster zu verwenden ... Ereignisse zu erstellen (entscheiden, wie generisch oder konkret ist eine andere Designentscheidung) und Ihre Objekte zu abonnieren, die sie benötigen.

Zum Beispiel kann Ihre Engine Collision- oder Proximity-Ereignisse auslösen, wenn sich 2 Entitäten in der Nähe befinden. Diese werden jedoch nur von den Entitäten empfangen, die interessiert sind. Sie können einige Optimierungen durchführen, um nur diese Bedingungen mit Beobachtern zu überprüfen.

Ich weiß nicht, ob das in Spielen üblich ist und ich habe es nie in irgendeinem Spiel (noch) verwendet, aber ich habe viele Male darüber nachgedacht und es ist die Option, die ich am meisten mag.

+1

Das Problem mit diesem ist aber, dass der Motor verantwortlich ist um all die Dinge zu überwachen, die passieren und Ereignisse auslösen, wenn sie gebraucht werden, im Gegensatz zu den Entitäten, die sich selbst unterhalten. –

3

Nun wäre ein Ansatz, eine Client/Server-Architektur einzurichten. Der Server würde also alle Aktualisierungen der Spielwelt und interne Logik verarbeiten und der Client würde nur den Server fragen, ob er bestimmte Aktionen ausführen kann. Der Server würde dann antworten und der Client würde dann nur den Spielbildschirm zeichnen und aktualisieren. Nicht-Spieler-Entitäten würden das gleiche tun. Der einzige Unterschied wäre, dass der Client menschlich gesteuert wird und die anderen Entitäten computergesteuert sind. Dies würde es dir erlauben, das Setup der Spielwelt und Ereignisse und Aktualisierungen von der Entitätslogik zu trennen.

Das "Nachrichtensystem", das Sie erwähnten, wird das Anwendungsprotokoll genannt und kann ein komplexes esoterisches Binärsystem oder einfache menschenlesbare Zeichenfolgen sein, die ich empfehlen würde. Während sich der Spieler bewegt, sendet der Server eine Liste von Objekten, die sich in Sichtweite des Clients befinden. Nichtspieler-Entitäten würden auf die gleiche Weise funktionieren. Dies geschieht, indem der Server nach der Berechtigung gefragt wird, Dinge zu tun, oder nach Informationen über eine andere Entität, die der Server zuvor gesendet hat, als er sich bewegte und in die Sicht der Entität kam und der Server mit der entsprechenden Antwort oder Information antwortete.

Wenn Sie dies mit Sockets implementieren würden, hätten Sie den offensichtlichen Vorteil des intrinsischen Netzwerkspiels, da es dem Server egal wäre, ob der Client sich auf demselben Computer verbindet, auf dem der Server läuft oder wenn der Client auf dem Kontinent ist . Das hat deine Frage vielleicht nicht speziell mit Code beantwortet, aber ich hoffe es war zumindest Denkanstoß.

+1

Auf jeden Fall Denkanstoß. :) –

2

Dies ist normalerweise viel einfacher, wenn Sie ein Objekt über der Entität haben, die die Verwaltung durchführt. (z. B. die "Welt" oder das "Spiel".) Es kann leicht erkennen, welche Entitäten sich in der Nähe der anderen befinden und dementsprechend Ereignisse und Benachrichtigungen senden.

Wenn Entitäten ein wenig mehr Kontext benötigen, um sinnvolle Entscheidungen zu treffen, wenn sie aktualisiert werden, können Sie die Welt immer in diesem Kontext in irgendeiner Form passieren lassen. Aber lassen Sie die Welt die Partitionierung und Platzierung von Entitäten verwalten, anstatt dass Entitäten sich direkt darum kümmern müssen.

(Auch, warum ein Quadtree? Für ein 2D-RPG ein grobes Raster wahrscheinlich viel einfacher wäre zu implementieren und gleichermaßen nützlich.)