time stamps richtig verwenden

      time stamps richtig verwenden

      Ich knabbere mal wieder an einem alten Problem... Wer mal versucht hat, ein Echtzeit-Onlinespiel zu programmieren, kennt dieses Problem:
      Wie kriege ich die "Events" zwischen den PCs synchronisiert, wenn alles mindestens 50ms Latenz hat?
      Das Thema ist im Profibereich weitgehend gelöst worden, bereitet mir allerdings im besten Fall Kopfschmerzen vom Lesen.

      Ich habe ein C64 BoulderDash geklont (wollte ich schon immer mal), aber es ist natürlich nur interessant wenn man wenigstens zu zweit spielt.
      Da das Spiel mit nur ca. 10fps läuft, gestaltet sich die Aufgabe vielleicht etwas einfacher.
      Zuerst habe ich den GM-Takt (room_speed) auf 999 geschraubt. Dann habe ich die Engine so kompakt gemacht, daß sie auf meinem PC mit immerhin noch über 800fps läuft.
      Ich benutze sogar den superschnellen HiResTimer, um das Spiel zu takten - Also wenns' so nicht geht...

      Das bekannte Problem ist: Ich muß die Daten vom Client zum Host schicken wo sie verarbeitet werden, und wieder zurück an den Client, zusammen mit bestimmten Ergebnissen. Dieses Bild zeigt in etwa, wovon ich spreche. Die 800fps sind nur dazu da, möglichst präzise arbeiten zu können. Ein Ping von 50 ms entspricht dann einer "round-trip" time von 100ms, also immerhin 1/10 Sekunde, was bei einem Spieltakt von 1/10 Sekunden wohl beträchtlich ist.



      Wenn inzwischen der nächste Takt eingetreten ist, kommen diese Daten aber erst im nächsten Step an.Ich kann diesen Fehler zwar reduzierieren indem ich den Takt vom Host gegen den vom Client verschiebe, aber das scheint nicht zu genügen.
      Üblich ist es vielmehr, die einzelnen Pakete irgendie mit sogenannten Zeit-Stempeln zu versehen und in eine Queue zu schieben. Damit ist es beiden (Host und Client) wohl möglich die Daten richtig einzusortieren. Und damit bin ich endlich bei meiner Frage angelangt:

      Wer kann mir helfen, BoulderDash mit GML und 39dll so zu bauen, daß der Client nicht das Gefühl hat in der Netzwerk-Steinzeit zu leben?
      Die Engine ist denkbar einfach. Es geht nur darum, für 1 Host und 1 Client die folgenden Events in den richtigen zeitlichen Ablauf zu bringen und eventuell eine Queue einzuführen.

      - Timer auslesen, Zeit speichern
      - Tastatur/Joystick auslesen und
      - an den Host senden (nur 1-2 bytes)
      - zulässige Bewegungen (auf dem Host) ermitteln und
      - Daten zurücksenden
      - Simulation (cave update) auf dem Host und
      - auf dem Client durchführen

      Ich habe es soweit fertig, daß fast alles auf eine Seite paßt. Genauer gesagt: zwei Step Events (host, client). Der Rest ist einfach zu simpel, um da mehr ins Detail zu gehen.

      Übrigens, wer Lust hat Levels zu bauen kann sich auch melden. Ich hab leider noch GM6, ich hoffe Ihr könnt das verwenden.
      Das kannst du leider nicht verhindern.
      Die meisten Online-Spiele arbeiten daher mit verschiedensten Techniken, damit es trotzdem ordentlich aussieht. Sinnvoll ist hierfür natürlich ein Dedicated-Server.

      Die Clients haben dabei ihre eigene Spielewelt, in der sie sich frei bewegen können. Ihre Aktionen und Bewegungen senden sie an den Server, wobei unwichtige Aktionen (Bewegungen) per UDP und wichtige (Attacken) per TCP versendet werden. Ein Paket zur Bewegung kann unter Umständen verloren gehen, da der Server die Bewegung recht sicher voraussagen kann und dies notfalls korrigiert, wenn das nächste Paket eintrifft. Der Client regelt die Bewegung und Kollisionen dabei selbt. Deshalb funktionieren in vielen Spielen auch Speedhacks.
      Wichtige Aktionen aber, wie Angriffe, Treffer von Gegnern etc. werden sicher übermittelt. Unter Umständen erreicht ein solches Event die Gegenseite erst spät, aber das ist meistens nicht schlimm.
      Wenn der Spieler z.B. noch gar nicht weiß, dass er tot ist und weiter angreift, stirbt er halt in dem Moment, in dem er auch die Nachricht bekommt. Dass er sich dabei auf dem Server noch etwas bewegt hat ist egal, die Leiche muss nicht unbedingt an exakt dem selben Ort liegen. Die Aktionen, die der Spieler in seiner "Scheintot"-Phase übermittelt hat, verwirft der Server einfach.
      Andersrum: Der Spieler sendet einen Angriff an den Server. Dieser ist zwar schon früher passiert, aber da alle Clients ihre Zeitstempel nach Eingang beim Server erhalten, bleibt eine gewisse Fairness erhalten. Es ist also nicht notwendig, dass der Server korrigiert, nur weil der Client sagt "aber ich hab mich doch rechtzeitig bewegt bei mir!". Hier kann man Frustration vermeiden, indem man mehr Spielraum zulässt und evtl. wieder Verhalten interpoliert (Bewegung).

      Ich kenn Boulder Dash nicht gut genug (ich hab es nur vor Ewigkeiten mal aufm C64 gespielt), aber ich behaupte einfach mal, dass du mit einer etwas anderen Rangehensweise dem Problem beikommen kannst.
      Naja, zum Glück entfallen bei diesem Projekt einige der üblichen Anforderungen. Das mit der Hack-Sicherheit zum Beispiel. Es soll auch nur 2 Spieler geben und nicht 1+x
      Außerdem gehe ich nicht davon aus, das Spiel mit meinem Bruder in den USA zu spielen, also rechne ich mit Pings < 50.
      Interpolation/Extrapolation entfallen (denke ich), weil das Spiel Grid-basiert ist und sich die Spieler immer um exakt ein Feld pro Takt bewegen.