Physikschleife in einer NodeJS / Socket.IO-Umgebung

8

Ich entwickle ein 2D-HTML5-Canvas-Spiel und versuche, den effizientesten Weg zu finden, um eine Physikschleife auf dem Server zu implementieren, indem NodeJS und Socket.IO ausgeführt werden.

Die einzige Methode, an die ich gedacht habe, ist die Verwendung setTimeout/Interval. Gibt es einen besseren Weg? Alle Beispiele wäre dankbar.

EDIT: Das Spiel ist ein Top-Down-Spiel, wie Zelda und ältere Pokemon-Spiele. Der größte Teil der in der Schleife durchgeführten Physik besteht aus einfachen Schnittpunkten.

Oyed
quelle
Sie sollten wahrscheinlich angeben, welche Art von Spiel Sie planen, insbesondere ist es schwierig, etwas über das Server-Timing zu sagen, ohne zu wissen, wie zeitkritisch Ihr Spiel sein wird.
aaaaaaaaaaa
Zelda ist viel zeitkritischer als Pokemon. Was ist übrigens die Multiplayer-Komponente? Warum muss das Spiel auf dem Server ausgeführt werden?
aaaaaaaaaaa
@eBusiness Es ist Multiplayer, denken Sie an MMORPG, wo es zu einem bestimmten Zeitpunkt viele Spieler in verschiedenen Bereichen von Maps gibt, die über den Server aktualisieren.
Oyed
Ich hatte das gleiche Problem. Die Spieleschleife
Impractical Labs

Antworten:

5

Ich glaube, es setTimeoutist gut genug für Ihre Bedürfnisse. Ich selbst stehe vor einer ähnlichen Situation und gehe mit setTimeout. Dieser großartige Artikel über BNG hat mir geholfen, besser zu verstehen, was ich tun (oder zumindest versuchen) muss: Echtzeit-Multiplayer in HTML5 .

Über den Link: Es geht hauptsächlich um die mehreren Spielschleifen und deren Vernetzung. Es ist ziemlich cool. Unten ein Auszug.

Wenn es um ein Echtzeitspiel geht, möchten wir die Spielelogik selbst auf dem Server UND dem Client ausführen. Dies liegt an der Tatsache, dass der Server jederzeit die Autorität für den Status des Spiels sein muss, der Client das Spiel jedoch auch lokal ausführen muss. Jeder Frame auf dem Server, der vom Netzwerk eingegeben wird, wird verarbeitet und auf die Spieler angewendet, und diese Änderung wird mit einer festen Rate an die anderen Spieler gesendet. Auf dem Client werden Eingaben gesammelt und an den Server gesendet, und Positionen können aktualisiert werden, während darauf gewartet wird, dass die Nachrichten vom Server zurückkommen (Client-Vorhersage).

Es ist eine sehr empfehlenswerte Lektüre. Zumindest von mir. = P.

Slacktracer
quelle
1
Sie sollten Ihrer Antwort mehr hinzufügen, damit zukünftige Benutzer wissen, wovon Sie sprechen, falls der Link stirbt.
@AlexM. Der Link ist eher eine Ergänzung und steht nicht in direktem Zusammenhang mit der Frage ... Aber Sie haben Recht. Es ist sowieso besser, es zusammenzufassen, wenn ich mich entschlossen habe, es dort abzulegen. =)
Slacktracer
1
In der Antwort könnte auch erwähnt werden, wie der Artikel vorschlägt, separate Schleifen für Physik-Updates (~ 60 fps) und Server -> Client-Updates (~ 20 fps) auf dem Server sowie separate Schleifen für Physik (~ 60 fps) und Client zu haben -> Server-Updates (so schnell wie möglich) auf dem Client. Die Trennung der io-Schleifen und der Schleifen zum Thema Physik ist das markanteste Merkmal dieses Artikels im Vergleich zu einigen anderen, die ich mir angesehen habe.
Max
2

Für serverseitige Inhalte haben Sie mehrere Optionen. Die erste besteht darin, alle Ihre Kollisionen vollständig zu extrapolieren, wobei davon ausgegangen wird, dass Sie häufig genug Nachrichten von Clients erhalten, und alle wichtigen Statusänderungen über den Server zu kommunizieren, der dann nur dann eine Validierung für Spielereignisse ausführt, wenn E / A-Rückrufe von der empfangen werden Client-Verbindungen.

Die zweite Möglichkeit, die Sie zu bevorzugen scheinen, besteht darin, eine eigene Schleife auszuführen, während Sie E / A-Rückrufe verarbeiten. Obwohl setInterval und setTimeout dies erreichen, verfügen Sie über eine viel feinere Reihe von Tools, um dies zu steuern: setImmediate(callbacks, [[arg], ...])und process.nextTick(callback).

Process.nextTick führt Ihren Rückruf vor anderen E / A- Ereignissen aus, solange Sie keinen rekursiv unendlichen Stapel von Rückrufen gestapelt haben (wenn er eine bestimmte Anzahl überschreitet, process.maxTickDepth, gibt er den E / A-Rückrufen nach).

SetImmediateCallback ähnelt process.nextTick dahingehend , dass es jeden Tick ausführt, aber nur einer der Rückrufe in der Warteschlange bei jedem Tick ausgeführt wird und nicht alle Rückrufe in der Warteschlange.

Die Verwendung dieser Elemente ähnelt setTimeout oder requestAnimationFrame.

function gameLoop() {
  updateCollisions();
  process.nextTick(gameLoop);
}

process.nextTick(gameLoop);

Dies hat den Vorteil, dass Sie nicht von der Implementierung von setTimeout und setInterval in V8 abhängig sind. Dies ist eher eine direkte Verbindung zur Ereignisschleife des Knotens. Stellen Sie nur sicher, dass Sie die E / A nicht verhungern lassen, wenn Sie process.nextTick verwenden. updateCollisions sollte garantiert nicht so lange dauern.

michael.bartnett
quelle
-1 requestAnimationFrame hängt von der Bildschirmaktualisierungsrate ab und ist nur für den Benutzercomputer relevant. Und für ein vernetztes Spiel möchten Sie wirklich nichts anderes als bildschirmunabhängige Physik mit fester Rate ausprobieren.
aaaaaaaaaaa
eBusiness ist richtig, requestAnimationFrame basiert auf einem Monitor, während die Schleife, die ich erreichen möchte, in NodeJS serverseitig ist.
Oyed
@eBusiness Sieht so aus, als hätte ich die Frage falsch gelesen und sie mit Material aktualisiert, das für Servercode und NodeJS relevant ist.
michael.bartnett
@ michael.bartnett In Bezug auf die Extrapolation aller Kollisionen basierend auf häufigen Paketen von Benutzern habe ich dies bereits implementiert, aber auf einem 60-FPS-Computer werden mehr Pakete gesendet, während 30 FPS eine halbe Anzahl von Paketen usw. usw. sind. Also, welche Implementierung davon würdest du empfehlen? Ich bin gerade ziemlich offen für Vorschläge. Das Beispiel, das Sie zur Verfügung gestellt haben, scheint ziemlich solide zu sein, aber wie Sie sagten, hängt es davon ab, dass die Kollisionsprüfung / Andere Physik ziemlich schnell ist. Dies ist in Ordnung, aber wenn es eine bessere Option gibt, die Sie kennen, teilen Sie sie bitte mit!
Oyed
@ThomasMosey Das ist eine breite und schwer zu beantwortende Frage, die ziemlich stark von den Besonderheiten Ihres Spiels abhängt. Insbesondere die Methode, bei der der Server keine eigene Logikschleife ausführt. Ein guter Ort zum Nachdenken ist die Antwort: Wem gehört jedes Objekt zu jedem Zeitpunkt im Spiel, was bewirkt, dass diese Objekte den Besitzer wechseln, und was muss objektiv verfolgt und vermittelt werden - das heißt, es gehört dem Server.
michael.bartnett