Kollisionsabfrage mehrerer Flotten und Flugzeit



  • Hallo zusammen,

    eventuell hat einer eine Idee?

    Ein Browsergame, viele Spieler haben eine oder mehrere Flotten, diese fliegen von Koordinaten x/y/z zu anderen x/y/z Koordinaten. Bei Ankunft soll geprüft werden ob am Ziel schon eine andere Flotte steht und ggf. einen Kampf auslösen.

    Meine Idee geht dahin:

    Bei Start wird in der DB die Ankunftszeit und Ziel gespeichert, ein serverseitiger Daemon fragt jede 0.5 Sekunde die Datenbank ab. In jeder Abfrage wird geprüft ob Zielzeit > als aktuelle Zeit. Bei Kollision wird ein Kampf ausgelöst und das Ergebnis in der Datenbank eingetragen. Das sollte auch funktionieren wenn kein Benutzer im Browser aktualisiert.

    Dürfte bei einer überschaubaren Anzahl an Flotten noch funktionieren, mit steigender Anzahl aber schnell die DB überfordern bzw. starke Verzögerungen auslösen.

    Hat einer einen besseren Ansatz?


  • Mod

    Spricht irgendetwas gegen die vermeintlich offensichtliche Lösung, bei jedem Statuswechsel eines Objekts zu prüfen, ob und welche Ereignisse dadurch ausgelöst werden?



  • Seppj, naja wenn die Flugzeit Minuten oder Stunden beträgt und ein anderer Spieler in dieser Zeit seine Flotte bewegt, kann der State vom Flugbeginn irrelevant sein.

    Also Spieler A fliegt zu Spieler B, Flugzeit 3 Minuten. Nach einer Minute fliegt Spieler B weg und ein anderer landet an den Zielkoordinaten.



  • @SeppJ sagte in Kollisionsabfrage mehrerer Flotten und Flugzeit:

    Statuswechsel

    "Flotte angekommen" wäre z.B so ein Statuswechsel.



  • Das ist eine Möglichkeit. Noch simpler ist es allerdings einfach gar nichts auszurechnen! Und wenn dann einer in der DB nachschaut, ob seine Flotte da ist, vergleicht man die Ankunftszeit und ändert die Daten der DB schnell noch, bevor man das Ergebnis ausgibt.



  • @TGGC sagte in Kollisionsabfrage mehrerer Flotten und Flugzeit:

    Das ist eine Möglichkeit. Noch simpler ist es allerdings einfach gar nichts auszurechnen! Und wenn dann einer in der DB nachschaut, ob seine Flotte da ist, vergleicht man die Ankunftszeit und ändert die Daten der DB schnell noch, bevor man das Ergebnis ausgibt.

    Vielleicht etwas allgemeiner formuliert würde ich sagen, dass das Programm nur dann etwas machen muss, wenn ein Ereignis eintritt, dass sich nicht vorherberechnen lässt.

    Das sind wahrscheinlich auschliesslich Nutzerinteraktionen, denn alles andere sollte nach festen Regeln und Algorithmen ablaufen, für die man direkt berechnen kann, wann in der Vergangeheit etwas passiert ist oder in Zukunft passieren wird (sofern dazwischen nicht eine komplexe Simulation abläuft, die man ohnehin nur iterativ sinnvoll lösen kann).

    Insofern, ja, es sollte reichen alles nur dann zu berechnen wenn "jemand nachschaut" - z.B. dass laut Datenbank und Flottenbewegungen vor <rechne... rechne...> 2 Stunden ein Kampf stattgefunden hat, der <rechne...rechne...rechne...> SO ausgegangen ist. Der erste betroffene Spieler der nachschaut, löst die Berechnung und das Speichern des Ergebnisses in der DB aus.

    P.S.: Einige Spiele verwenden einen solchen Ansatz, um die Netzwerklast zu reduzieren und gut skalieren zu können. Factorio ist meines Wissens ein Beispiel dafür. Soweit ich weiss werden dort bei einem Mehrspieler-Netzwerkspiel ausschliesslich Nutzereingaben mit Zeitstempel übertragen. Die Simulation der riesigen Fabrikanlagen läuft auf jedem Client getrennt und ist dennoch synchron, da nur eine Nutzerinteraktion das Ergebnis der Simulation verändern kann.



  • Vielen Dank für die Antworten.

    Ich werde mal was richtung SMO / Cpp probieren.

    Also ein, als Service / Deamon, dauerhaft laufendes Programm hält alle Fluginformationen. Neue Flüge werden über ein SMO hinzugefügt. In Net Core müsste ich es auch als Lib mit PInvoke vor Kestrell einbinden können.

    Das Programm prüft in einem Thread die Flugzeit und berechnet den Kampf.

    Bei Start werden alle Infos aus der DB geladen und Änderungen in die DB geschrieben.

    In einer cpp liste sollte eine sechs oder siebenstellige Anzahl an Fluginformationen kein Speicherproblem darstellen. Statisch gehalten werden müssten nur id, Startzeit und Flugzeit.



  • Was meinst du mit SMO? Die Abkürzung kann für sonst was stehen.
    Warum Cpp und .NET Core und PIvoke? Zumindest anhand der bisherigen Informationen sehe ich dafür keinen Grund. Wenn du das mit .NET machen willst, dann mach es. Wenn du die Daten als struct verwaltest, gibt es vom Speicherverbrauch her keinen Unterschied. Wenn du Klassen verwendest, wird es einen Unterschied geben, aber der sollte vernachlässigbar sein.



  • @Mechanics
    SMO = Shared Memory Objects

    Warum Cpp und .NET Core und PIvoke? Das ganze wird eine NetCore App in F# mit Websharper/React. Das Handling von vielen mutable Objects ist in F# nicht schön und generell teuer, auch in C#. Eine sechs- oder siebenstellige Anzahl von Structs in einer .net Liste? Das düfte jeden Stack zerlegen. Als Klasse, bringt der Garbage Collector alles, in regelmäßigen Abständen, kurz zum Erliegen. Operationen in der Liste lassen den Speicher kurzfristig explodieren, falls er denn dann wirklich freigegeben wird. Nicht falsch verstehen, ich mag .net, nur dafür nicht das richtige.



  • @Marco sagte in Kollisionsabfrage mehrerer Flotten und Flugzeit:

    Eine sechs- oder siebenstellige Anzahl von Structs in einer .net Liste? Das düfte jeden Stack zerlegen.

    Nope. Denn eine .Net liste wird nicht auf dem "stack" angelegt. Eine .Net Liste ist ein Reference Type.



  • @Marco sagte in Kollisionsabfrage mehrerer Flotten und Flugzeit:

    Nicht falsch verstehen, ich mag .net, nur dafür nicht das richtige.

    Nicht falsch verstehen, ich kenn mich zur Zeit mit C++ besser aus, als mit .NET 😉
    Ich halte es aber für sehr wahrscheinlich, dass deine Annahmen nicht zutreffen, bzw. sich in den Griff kriegen lassen, oder einfach irrelevant sind. C# dürfte absolut in der Lage sein, mit so großen Listen umzugehen.


Log in to reply