Erstellen Sie eine nahtlos wiederholbare 2D-Multiplayer-Ebene?


15

Kürzlich wurde darüber diskutiert, wie man ein 2D-Side-Scrolling-Multiplayer-Spiel erstellt, das ein Loop-Level-Design haben kann (Denken Sie an Starbound und wie sich ihre Welten im Loop bewegen).

Ich dachte, der einfachste Weg wäre eine rechteckige Karte mit Triggerzonen, die Spieler von einer Seite zur anderen teleportieren könnten. Das offensichtliche Problem bei diesem Ansatz ist jedoch, dass sich mehrere Spieler gleichzeitig am Rand der Karte befinden. Du willst nicht nur Spieler voreinander teleportieren und brauchst eine Möglichkeit, Spieler zu transportieren, ohne dass andere Spieler verschwinden.

Um diese Idee anzufügen und das Problem zu beheben, habe ich mir Folgendes ausgedacht: eine Triggerzone (rotes Quadrat im Bild), in der Spieler eine "Klonzone" (grünes Quadrat) sehen können. In diesem grünen Quadrat werden Objekte von der gegenüberliegenden Seite der Triggerzone in die entsprechende Klonzone kopiert (erkennbar an den Formen A und B). Wenn ein Spieler die Startkante der "Klonzone" erreicht, wird er auf die andere Seite der Karte teleportiert.

Bild

In diesem Beispiel würde Spieler 2 denken, dass er Spieler 1 sieht, aber tatsächlich würde er seinen Klon sehen und umgekehrt.

Dies schien für das vorliegende Problem etwas extrem und komplex zu sein. Meine Frage ist nun, ob diese Lösung ein guter Ansatz zur Lösung des Problems ist oder ob es einen einfacheren Weg gibt, dieses Problem zu lösen.


Dürfen Spieler in ein vorheriges Gebiet zurückkehren?
XiaoChuan Yu

Ja, hin und her, es gibt eine Art "um die Welt laufen" -Effekt. Ähnlich wie eine Welt in Starbound ist
KenQueso

2
Haben Sie darüber nachgedacht, die Welt zu einem großen Kreis zu machen? Oder den Level als großen Kreis behandeln und in eine flache 2D-Bühne übersetzen?
Nzall

Können Sie die Kameraposition nicht immer auf den zu steuernden Player ausrichten?
Ali1S232

Antworten:


16

Dieses System mit all diesen Triggern klingt etwas zu kompliziert und fehleranfällig.

Sie könnten die Position des Players mit modulo mit so etwas wie umschließen playerPositionX = playerPositionX % mapWidth

Auf diese Weise , wenn der Spieler erreicht playerPosition == mapWidthdas playerPositionwird auf 0 zurückgesetzt.

Diese Lösung könnte mit dem gesamten Renderingsystem erweitert werden.


1
Hätte dies nicht das Problem, dass Spieler, deren Position zurückgesetzt wurde, in der Nähe sind und Spieler sehen, die sich teleportieren?
KenQueso

Wie würden Sie dies auf das Rendering-System ausweiten?
Mikael Högström

Sie könnten einen Spieler immer in der Mitte der Kamera haben und die Karte herumwickeln lassen. Wie eine Karte in der Zivilisation auf Erden. Ein anderer Ansatz könnte darin bestehen, den sichtbaren Teil eines Spielers auf beiden Seiten der Karte darzustellen.
Exaila

4
@ MikaelHögström Einfach wie gewohnt rendern, aber Dinge, die sich in der Nähe des rechten Randes befinden, müssen ein zweites Mal links (dh um pos - map_width) gerendert werden .
Mario

1
An jeder Stelle in Ihrem Code, an der Sie nach "Was für ein Objekt befindet sich an dieser Koordinate" oder "Was sind die Koordinaten dieses Objekts" suchen, würden Sie es zu xcoord% mapWidth machen. Es ist schwer zu sagen, ohne Ihren Code, aber das würde wahrscheinlich dazu führen, dass er korrekt gerendert wird.
Tin Man

13

Die kanonische Lösung besteht darin, Portale zu verwenden . In Ihrem Beispiel gibt es nur eine Ebene, außer dass ein Portal das linke und das rechte Ende verbindet.

Wenn sich etwas über dieses Portal bewegt, werden die Koordinaten an das andere Ende des Portals verschoben. Wenn sich also etwas links durch das Portal bewegt, wird es auf der rechten Seite des Levels wieder angezeigt und umgekehrt.

Ihre Kamera muss auch die Portale unterstützen. Befindet sich das Portal in der Kamera, muss es Teile der Ebene auf beiden Seiten des Portals rendern. Wenn Sie mit Bildbearbeitungsprogrammen für nahtlose Kachelgrafiken vertraut sind, ist dies auch hier der Fall.

Der mühsame Teil ist, dass alles, was mit Distanz oder Pfadangaben zu tun hat, auch Portale unterstützen muss. Dies beinhaltet KI, Sichtlinienalgen, Schalldämpfung und so weiter.

Das Schöne an Portalen ist, dass es sehr mächtig ist. Die Build-Engine simulierte damit mehrstöckige Level, obwohl es sich nicht um eine "echte" 3D-Engine handelt. Einige moderne Motoren verwenden auch Portale, um nichteuklidische Räume zu erstellen. Portal und Vorkammer sind bemerkenswerte Beispiele in 3D.


2
Wenn Sie sich den Kommentar des Portalspiels anhören, wird ein Teil der Funktionsweise von Portalen implementiert, indem Sie das klonen, was durch das Loch sichtbar ist. (aber aus physikalischen Gründen anstatt Rendering)
Mooing Duck

6

Denken Sie daran, dass das, was Sie auf dem Bildschirm anzeigen und was sich im Speicher befindet, zwei völlig verschiedene Dinge sind. Stellen Sie sich vor, Sie haben ein Fenster, das Sie mit Daten über die Welt füllen müssen. Sie füllen das Fenster von links nach rechts. Während Sie Ihre Daten analysieren, um die Welt zu füllen, kehren Sie einfach zum Anfang Ihrer Daten zurück, wenn Sie das Ende der Welt erreichen. Die Verwendung einer Modulo-Operation ist ideal. Denken Sie daran, dass Sie dies für alles tun müssen . Projektile, Strahlen, Spieler, Physik; Sie alle müssen ihre Positionen eingepackt haben, wenn sie die Grenzen der Welt überschreiten.

Jeder Spieler teilt Daten, hat jedoch eine eigene Perspektive der Daten. Ihre Fenster sind unterschiedlich bevölkert, je nachdem, wo sie sich auf der Welt befinden.

Dies bedeutet, dass Sie keine Klone erstellen oder jemanden teleportieren müssen. Im Wesentlichen Sie sind die Schaffung Klonen, nur durch Zeichen zu jedem der anderen Bildschirmen zu machen.


3

Trennen Sie das Rendern von der Welt, und Sie können das Rendern umbrechen und korrigieren, ohne auf Klonen oder Teleportieren von Artefakten zurückgreifen zu müssen.

Erstens haben Sie in Ihrer Welt eine Welt mit fester Größe von 0bis Width. Immer wenn ein Objekt unter 0 fällt, wird es bis zum Ende umgebrochen und jedes Mal, wenn ein Objekt vorbei istWidth überdeckt wird, wird es bis zum Anfang . Dies bedeutet, dass alle logischen Objekte in Ihrer Welt immer in Reichweite sind 0...Width.

Zweitens werden Sie für das Rendern Modulo für die Position ausführen. Die linke Seite des Bildschirms ist "Basis" und die rechte Seite ist "Basis + Größe". Sie suchen also in Ihrer Welt nach etwas in diesem Bereich. Sie suchen tatsächlich nach dem Modulo-Bereich, dem er zugeordnet ist0...Width .

Der Trick bei der Suche besteht darin, die Position des Objekts relativ zum zurückzugeben Base linken Seite zurückzugeben. Dies wird in lokale Koordinaten des Bildschirms konvertiert, sodass sich der Renderer selbst nicht um das Modulo kümmern muss, sondern nur um die Suche.

Sie müssen nichts klonen, da jeder Renderer das Objekt nur an einem Ort bearbeitet.

Wenn Ihre Welt in Segmenten oder mit 3D-Strukturen erstellt wird, müssen Sie sie segmentieren. Daher ist es kein zusammenhängender Block, sondern kann verschoben werden, um diesem Rendering Rechnung zu tragen. Sie brauchen nicht viele Blöcke, mindestens 2.


1

Ich denke, der einzig vernünftige Ansatz wäre, Ihre verpackte Welt in einer zugrunde liegenden Datenstruktur zu implementieren, die für das Spiel und den Benutzer völlig transparent ist. Auf einigen Low-Level-Karten haben Sie also eine Funktion mapCoordinate (), die Ihre tatsächlichen Koordinaten in die zugrunde liegende Kartenressource einfügt ...

Wenn Ihre tatsächliche Welt also nur 10 Einheiten breit ist, werden der Spieler und das Spiel es nicht wissen. Für den Spieler ist die Welt unendlich - und wenn das Spiel fragt, was sich auf Position 15 befindet, übersetzt die zugrunde liegende Funktion diese Anforderung modulo10 und gibt den Gegenstand auf Position 5 ein.

Für die gesamte Spiellogik und alles andere ist es so, als hätte man eine unendlich große Welt, in der es zufällig Kopien von allem gibt.


1

Es ist nicht ganz dasselbe, aber ich habe etwas Ähnliches bei einem Game Jam implementiert. Das Spiel hatte Spieler, die sich auf einer kleinen kreisförmigen Ebene bewegten und herumgewickelt wurden, als der Spieler eine 'x'-Position von pi erreichte. Das Rendern war einfach, da wir einfach alles gerendert und dann eine Offset-Kamera gedreht haben, um zu verfolgen, was gerade vor sich ging. Sie könnten etwas Ähnliches implementieren, wie oben vorgeschlagen wurde:

  • Überprüfen Sie beim Zeichnen die Kameraposition und bestimmen Sie, was unter Berücksichtigung der Kameraposition und des Sichtbereichs gezeichnet werden muss.
  • In Fällen, in denen die Kamera über den 'Rand' der Karte hinaus sieht, wählen Sie eine geeignete Menge an Inhalten auf der anderen Seite der Welt aus, um über diesen Rand zu zeichnen, indem Sie in der Regel die Breite der Ebene zu ihrer Position hinzufügen oder abziehen.
  • Die Spielelogik muss sich dieser Naht bewusst sein und sich darauf einstellen, wie in anderen Antworten erwähnt. Besondere zu beachtende Fälle sind Kollisionen, bei denen sich ein Objekt auf der einen Seite befindet, aber mit einem Objekt auf der anderen Seite kollidiert.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.