Hintergrund
Zusammen mit einem Freund arbeite ich an einem 2D-Spiel, das im Weltraum spielt. Um es so immersiv und interaktiv wie möglich zu gestalten, möchten wir, dass Tausende von Objekten frei herumschweben, einige zusammen gruppiert, andere im leeren Raum treiben.
Herausforderung
Um die Rendering- und Physik-Engine zu entlasten, müssen wir eine Art räumliche Partitionierung implementieren. Wir müssen zwei Herausforderungen bewältigen. Die erste Herausforderung besteht darin, dass sich alles bewegt, sodass die Rekonstruktion / Aktualisierung der Datenstruktur extrem kostengünstig sein muss, da sie in jedem Frame durchgeführt werden muss. Die zweite Herausforderung ist die Verteilung von Objekten, wie bereits erwähnt, dass es möglicherweise Cluster von Objekten und riesige Teile des leeren Raums gibt, und um es noch schlimmer zu machen, gibt es keine Grenze zum Raum.
Bestehende Technologien
Ich habe mir vorhandene Techniken wie BSP-Bäume, QuadTrees, kd-Bäume und sogar R-Bäume angesehen, aber soweit ich das beurteilen kann, passen diese Datenstrukturen nicht perfekt zusammen, da viele Objekte aktualisiert wurden, die in andere Zellen verschoben wurden ist relativ teuer.
Was ich versucht habe
Ich habe die Entscheidung getroffen, dass ich eine Datenstruktur benötige, die mehr auf schnelles Einfügen / Aktualisieren ausgerichtet ist als auf die Rückgabe der geringstmöglichen Anzahl von Treffern bei einer Abfrage. Zu diesem Zweck habe ich die Zellen implizit gemacht, damit jedes Objekt anhand seiner Position berechnen kann, in welcher Zelle (n) es sich befinden soll. Dann verwende ich eine HashMap
, die Zellkoordinaten auf eine ArrayList
(den Inhalt der Zelle) abbildet . Dies funktioniert ziemlich gut, da bei "leeren" Zellen kein Speicher verloren geht und es einfach ist zu berechnen, welche Zellen untersucht werden sollen. Das Erstellen all dieser ArrayList
s (Worst Case N) ist jedoch teuer und wächst häufig HashMap
(obwohl dies durch eine große Anfangskapazität leicht gemildert wird).
Problem
OK, das funktioniert, ist aber immer noch nicht sehr schnell. Jetzt kann ich versuchen, den JAVA-Code zu optimieren. Ich erwarte jedoch nicht zu viel davon, da der Profiler mir sagt, dass die meiste Zeit für die Erstellung all der Objekte aufgewendet wird, die ich zum Speichern der Zellen verwende. Ich hoffe, dass es einige andere Tricks / Algorithmen gibt, die dies viel schneller machen. So sieht meine ideale Datenstruktur aus:
- Die Priorität Nummer eins ist die schnelle Aktualisierung / Rekonstruktion der gesamten Datenstruktur
- Es ist weniger wichtig, die Objekte fein in gleich große Bins zu unterteilen. Wir können ein paar zusätzliche Objekte zeichnen und ein paar zusätzliche Kollisionsprüfungen durchführen, wenn dies bedeutet, dass die Aktualisierung etwas schneller ist
- Speicher ist nicht wirklich wichtig (PC-Spiel)