Bewegungssynchronisation auf Multiplayer-Kachelbasis

8

Ich muss die Bewegung mehrerer Spieler über das Internet synchronisieren und versuche herauszufinden, wie dies am sichersten ist.

Das Spiel basiert auf Kacheln, Sie können sich nur in 4 Richtungen bewegen und jede Bewegung bewegt das Sprite 32px (natürlich im Laufe der Zeit). Wenn ich diese Verschiebungsaktion einfach an den Server senden würde, der sie an alle Spieler sendet, während die Walk-Taste gedrückt bleibt, um weiterzulaufen, muss ich diesen nächsten Befehl ausführen und an den Server senden. und für alle Kunden, rechtzeitig, oder die Bewegung wird nicht mehr reibungslos sein. Ich habe das in anderen Spielen gesehen und es kann ziemlich schnell hässlich werden, auch ohne Verzögerung. Ich frage mich also, ob dies überhaupt eine praktikable Option ist. Dies scheint jedoch eine sehr gute Methode für Einzelspieler zu sein, da es einfach und unkompliziert ist (nehmen Sie einfach die nächste Bewegungsaktion rechtzeitig vor und fügen Sie sie einer Liste hinzu) und Sie einfach Mausbewegungen hinzufügen können (Klicken auf eine Kachel). Um einer Warteschlange einen Pfad hinzuzufügen, wird dieser ausgeführt.

Das andere, was mir in den Sinn kam, war das Senden der Information, dass sich jemand in eine Richtung bewegt hat, und erneut, sobald er angehalten oder die Richtung geändert hat, zusammen mit der Position, damit das Sprite an der richtigen Position erscheint, oder besser gesagt, dass Die Position kann festgelegt werden, wenn sie falsch ist. Dies sollte (hoffentlich) nur dann zu Problemen führen, wenn jemand wirklich zurückbleibt. In diesem Fall ist dies zu erwarten. Damit dies funktioniert, würde ich allerdings eine Art Warteschlange benötigen, in der eingehende Richtungsänderungen und andere Dinge gespeichert werden, damit das Sprite weiß, wohin es gehen soll, nachdem die aktuelle Bewegung zur nächsten Kachel abgeschlossen ist. Das könnte tatsächlich funktionieren, klingt aber irgendwie zu kompliziert. Obwohl dies möglicherweise der einzige Weg ist, ohne das Risiko eines Stotterns. Wenn auf der Client-Seite ein Stopp oder eine Richtungsänderung eingeht, wird ' s wird in einer Warteschlange gespeichert und das Zeichen bewegt sich weiter zu den angegebenen Koordinaten, bevor es stoppt oder die Richtung ändert. Wenn der neue Befehl zu spät kommt, wird es natürlich auch stottern ...

Es fällt mir schwer, mich für eine Methode zu entscheiden, und ich konnte noch keine Beispiele dafür finden. Mein Hauptproblem ist es, die Kachelbewegung reibungslos zu halten, weshalb andere Themen zur Synchronisation pixelbasierter Bewegungen nicht allzu viel helfen.

Was ist der "Standard" Weg, dies zu tun?

Mars
quelle

Antworten:

4

Ich gehe davon aus, dass Sie davon sprechen, sich in Echtzeit zu bewegen. Der Versuch, die Position zu interpolieren, ist wahrscheinlich eine verlorene Ursache. Bei einer langsamen Verbindung kann Ihr Spielstatus immer weiter hinter den tatsächlichen Spielstatus zurückfallen. Im Gegensatz zu dem anderen Kommentar würde ich davon abraten, viel Spielelogik auf die Serverseite zu setzen. Wenn ich diese Art von Lösungen implementiert habe, hat der Client ständig einen TCP-Socket zum Server. Wenn sich der Spielstatus ändert, wird eine Nachricht an den Server gesendet, z. B. "Client ist bei x = 10, y = 20". Der Server leitet die Nachricht an die anderen Clients weiter, die versuchen, sie basierend auf ihrer eigenen internen Logik zu verarbeiten. Durch die Verwendung von TCP wird sichergestellt, dass Ihre Nachrichten in der richtigen Reihenfolge ankommen.

Leider können selbst AAA-Spiele keine extreme Verzögerung bewältigen. Spieler bewegen sich gelegentlich sehr schnell, weil ihre lokalen und Netzwerkzustände weit aus dem Ruder gelaufen sind. Das Überwachen des Round-Trip-Pings und das Treten von Benutzern, die zu weit / langsam sind, hilft dabei.

Alan Gardner
quelle
1
+1 für "Selbst AAA-Spiele können mit extremen Verzögerungen nicht umgehen." Eigentlich kann niemand auch kleine Verzögerungen perfekt bewältigen. Wir können es so aussehen lassen, wie wir es können.
Valmond
3

Grundsätzlich können Sie dies auf einfache und sichere Weise tun (Warnung, extremer Pseudocode):

A) Der Client (Spieler-ID = 5) fordert den Server auf, sich nach rechts zu bewegen (oder besser, um 73,18 zu kacheln).

B) Der Server überprüft seine große 2D-Karte, die Spieler enthält (oder beispielsweise die Spieler-ID):

 if(map[73][18] == occupied)
     Send back ('Not OK') to client (the case is blocked by another player)
else
    Set the new position as blocked: map[73][18]=5
    Release the old position: map[72][18]=0;
    Send a 'new position: 5, 73,18' message to all players who are nearby (moving client included)

C) Kunden erhalten eine Nachricht "Neue Position" (oder Spieler 5 erhält die Nachricht "Nicht in Ordnung").

D) Clients bewegen den Gegenstand mit Spieler-ID = 5 langsam in Richtung seiner neuen Position (oder erstellen ihn, wenn er keinen Gegenstand mit Spieler-ID = 5 hat).

Valmond
quelle
Nun, danke, aber mein Problem ist es, es für die anderen Kunden über mehrere fortgesetzte Kachelbewegungen hinweg reibungslos zu halten, nicht die Kachelbewegung im Allgemeinen ^^
Mars
Stellen Sie die Geschwindigkeit richtig ein und kompensieren Sie die Verzögerung, zum Beispiel mit einer toten Rechnung oder nur einer "dummen" Bewegung in Richtung Ziel mit konstanter Geschwindigkeit (oder proportionaler Geschwindigkeit über eine bestimmte Schatzkammer, wenn Sie Zeitstempel entlang von Positionen senden), und es sollte Ihnen gut gehen.
Valmond
1

Ich denke, die von Ihnen beschriebene Methode ist ziemlich gut, besonders in einem simplen Spiel, in dem nur 4 Züge erlaubt sind. Hier ist, wie ich es implementiert habe.

Ich kenne keine Standards, aber das erste, was mir in den Sinn kam, war, nur "Eingabeänderungen", Änderungen in der Eingabe eines Spielers, von einem Spieler an die anderen zu senden. Sie können beispielsweise nur Nachrichten im Sinne von [Taste gedrückt, Tasten-ID, Uhrzeit] oder [Taste freigegeben, Tasten-ID, Uhrzeit] senden und das Spiel der Spieler auf diese Eingabeänderungen reagieren lassen. Das Einbeziehen der Zeit hilft bei der Pfadkorrektur (wenn der Spieler zum Zeitpunkt t die Richtung geändert hat, muss das "Vorwärtsgehen" zum Zeitpunkt t + 1 festgelegt werden).

Bei dieser Lösung kann es jedoch zu Problemen mit verlorenen Nachrichten kommen. Angenommen, die Nachricht "Schlüssel freigegeben" wurde nie gesendet? Dies kann dazu beitragen, den Spielstatus eines Spielers regelmäßig abzufragen und die aktuelle Position des Spielers sowie alle gedrückten Tasten oder sogar den gesamten Spielstatus zurückzugeben. Abhängig von der Anzahl der Spieler und Befehle können Sie diese anpassen, um die Nachrichtenübermittlung zwischen Clients / Servern für ein ausgewogenes Verhältnis auszugleichen.

Eine andere Sache, die Sie untersuchen können, ist die Pfadplanung. Wenn sich der Spieler beispielsweise 5 Sekunden lang vorwärts bewegt hat, ist es wahrscheinlich, dass sich der Spieler in der nächsten Millisekunde immer noch vorwärts bewegt. In diesem Fall können Sie einen Anschein einer Pfadvorhersage erstellen, um Verzögerungen zu vermeiden. Dies ist im Wesentlichen das, was die obige Methode tut, obwohl dies Kreisbahnen berücksichtigen kann.

Ich hoffe das hat geholfen!

Jonathan Pitre
quelle
1
Das Problem beim Senden von Eingaben besteht darin, dass Ihr Spielstatus nicht mehr in Ordnung ist, wenn Sie eine einzelne Eingabe verpassen oder sie manchmal nur in der falschen Reihenfolge interpretieren. Zwei Clients zeigen unterschiedliche "Bildschirme" an.
Valmond
@ Valmond sehr guter Punkt ... in der Tat möchte ich meine Antwort löschen, da es sich in diesem Licht falsch anfühlt.
Jonathan Pitre
1
Sie können die Eingaben an den Server senden (bis es in Ordnung ist), aber der Server sollte (IMO) genaue Daten senden oder zumindest die Daten überprüfen oder möglicherweise den gesamten Spielstatus senden (dies wurde in echten Spielen durchgeführt, zum Beispiel Blood Bowl ), vielleicht können Sie Ihre Antwort optimieren, anstatt sie zu löschen :-)
Valmond