Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Hallo allerseits,
Zwischen all dem Kram, mit dem ich mich sonst beschäftigen muss, denke ich ab und zu auch über das Strategy Game nach. Dabei bin ich auf ein ernsthaftes Problem was den Speicherverbrauch betrifft gestoßen. Und zwar, wie aus dem Konzept her zu ersehen, ist ja geplant, die Planetenoberflächen relativ detailliert verwalten zu lassen. D.h., Gebäude platzieren, Einheiten und und und.
Nun ist mir aber aufgegangen, was passiert, wenn ich Planeten mit durchschnittlichen 256x256 Feldern (so rein theoretisch, ich denke, das wird wohl nötig sein, um ein einigermaßen angenehmes Spielgefühl zuzulassen) habe... Dann eine große Galaxie, mit 50 Systemen, die im Optimalfall 250 Planeten haben... Kurze Rechnung: 16.384.000 Felder, die zu verwalten sind. Das schließt ein: Höheninformation, Belegt/Nicht-belegt, Besitzer (evtl.), Ressourcen (evtl.)... Höheninformation mindestens 1 Byte, Belegt/nicht-belegt (und andere Flags) nochmal ein Byte, Besitzer auch ein Byte, Ressourcen lasse ich erstmal außen vor. Das läuft also auf 3 Byte pro feld, läuft also auf 49.152.000 Byte hinaus, rund 47 MiB. Leider wird diese Menge an Speicherplatz nicht nur zur Laufzeit sondern auch im Savegame benötigt und hier wirds haarig.
Wenn ich das ganze full featured mache, so wie ich es ursprünglich (bevor ich diese Rechnung durchgeführt hatte), geplant hatte, wären das 7 Byte pro Feld, aufgerundet auf 8, 131.072.000 Bytes, also 125 MiB für das gesamte Spiel. Dazu kommen dann noch alle möglichen Objekte wie Gebäude, Spieler, Forschungen, Einheiten usw usf. Ich finde schon das obere in Hinblick auf die Saves zu viel... Wenn ich jetzt hierrüber nachdenke wird mir fast übel.
Nun habe ich überlegt, wie ich da ran gehe:
-> Ich nehme die abgespeckte Feldinformation. Das sorgt für ein paar Einschränkungen im Gameplay (keine Ressourcenfelder, Ressourcen demnach gleichmäßig auf dem Planeten verteilt, damit ließe sich noch leben).
-> Ich ignoriere den Speicherverbrauch einfach und sage, man braucht halt nen guten Rechner (was auf das verhalten aktueller Spielefirmen hinausliefe)
-> Ich versuche, die daten zur laufzeit zu komprimieren, wenn sie nicht gerade gebraucht werden (kommt nicht in Frage für die Serverseite)
-> Ich kille die Einheiten aus dem Spielkonzept (das würde das Flag-Byte ersparen. Die Informationen würden nicht so oft gebraucht dass sich das speichern im Map-Array lohnen würde). Das würde ich auch soweit favorisieren, zumal das einiges erspart, wenn da nicht das Problem wäre, dass man dann keine möglichkeiten hinsichtlich der feindlichen Gebäude hat (Einnehmen, Infiltrieren usw usf), etwas, was ich eigentlich schon fest im Blick hatte. Dafür bräuchte ich eine Alternative... Fürs Übernehmen könnte man eventuell ein Hacking-Kommando von einem Schiff aus durchführen oder sowas.
-> Nur fürs Savegame: Man könnte im Save nur den Seed, der fürs erzeugen der Heightmap verwendet wurde speichern und dann weiterhin alle Änderungen, die im Spielverlauf daran gemacht wurde.
So... Jetzt brauche ich etwas Beratung von Euch... Wie würdet Ihr an das Problem rangehen?
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Das Universum mit seinen Systemen mit ihren Planeten hast du doch bestimmt irgendwo definiert, in einer Map-Datei oder ähnlichem, oder?
Da rein halt die ganze Welt mit ihren Eigenschaften. Einmal die Grundeigenschaften der Felder selbst definiert (Höhe etc.) und dann noch irgendwo eine Liste mit Spielfeldeigenschaften (Welcher Spieler besitzt am Anfang welches Feld mit welchen Gebäuden oder was auch immer).
Dann brauchst du für ein Savegame da nur ein Delta zwischen Ausgangssituation und jetziger Situation bilden und das abspeichern. Rekonstruieren wäre dann die Welt laden und das Delta da wieder draufpacken.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ja, das Problem bei der sache ist, dass alles Zufällig generiert wurde. Aber deine Idee habe ich ja auch schon aufgegriffen: Den Seed vom Zufallsgenerator speichern, das Universum beim Laden komplett neu generieren und dann das Delta darauf anwenden. Der Haken dabei ist natürlich, dass ich dann beim Speichern immer das komplette Delta berechnen muss.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Entweder berechnen oder irgendwo mitführen. Was du ja eigentlich sowieso tust. Würde die Datenstruktur so ca aufbauen:
- Auf den Zellen nur Umweltinformationen haben.
- Eine Liste führen pro "spielveränderter" Zelle: Welcher Spieler sie besitzt, was darauf geparkt ist an Einheiten usw.
-> Diese Liste müsstest du nur speichern. Wobei wenn jedes Feld im Universum komplett besetzt ist, wird's wieder witzig mit dem Speicher. Aber naja...
-> Spielstände in komprimierten Dateien speichern sollte auch jede Menge bringen.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ja, ich könnte natürlich das über Listen laufen haben. Aber beim Pathfinding wird das ganze schon ganz anders aussehen. Schließlich brauche ich da möglichst schnellen und reibungslosen Zugriff auf die Pro-Feld-Informationen. Und das ginge am besten direkt auf der Map. Wenn ich dann immer erst raussuchen muss, ob da eine Einheit steht, ist das äußerst inperformant. Was natürlich ginge ist, diese Informationen immer erst zu dem Zeitpunkt aufzubauen, an dem der Planet aufgerufen wird. Wobei der Server die fast trotzdem dauernd parat haben muss....
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Hmmm... Vor dem selben Problem stand ich ca. 2005. Damals wollte ich zusammen mit einigen Kommilitonen eine Planeten für ein Spiel abbilden.
Wenn ich höre, was du machen willst, würde ich dir Vorschlagen das Prinzip eines Quadtrees (bzw. des JPG) auf deine Datenstruktur anzuwenden.
Deine Welt ist zu 95% leer.
Klingt deprimieren, ist aber so. Leere Welt verbraucht nur unnötig Speicherplatz.
Du gehst also hin, und unterteilst deine Welt in sagen wir mal 6x6 Hauptpatches. Die Patches werden verbunden über Zwischenstücke, welche dafür sorgen, dass der Nutzer den Übergang zwischend en Patches nicht so deutlich merkt.
Für jeden Patch verwendest du Perlin Noise um den Untergrund zu bestimmen. Und auch um die Ressourcen zu verteilen.
Wenn jetzt irgendwo eine Basis gebaut wird, unterteilst du den Patch nach dem Quadtree verfahren rings um die Basis herum. Wird irgendwo an den Ressourcen rumgebaggert kommt der Differenz-Speicher-Ansatz zum tragen. Differenzen musst du dann aber nur noch für Felder in der nähe einer Basis speichern.
Einheiten kannst du auf den Hauptpatches frei bewegen. Das Raster muss nicht verfeinert werden. Erst wenn der Spieler sich die Einheit live ansieht, unterteilst du live die Umgebung rings um die Einheit und generierst daraus den Untergrund. Sobald sich feindliche Truppen näher als x-Einheiten kommen, unterteilst du deren Umgebung immer, um keine Rechenfehler einzuschleusen. (Nicht das Truppen auf grund von Rundungsfehlern, plötzlich Blockaden durchbrechen. )
Soweit meine Idee für einen Planeten.
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Eine sehr Sparsamme Möglichkeit ist folgende.
Dein Algorythmus, der das Universum zufällig aufbaut, sollte solide sein und bei gleichen Seed immer gleiches ergebnis bringen.
Ideal ist hier Perlin Noise Algorythmus, da er sehr stark variierende Werte liefert aber bei gleichem Seed immer exakt gleich sind.
Die Zufallszahlen sind nur die Steuerung, was den Content wirklich erstellt ist die Logik.
Was du nun machst ist den Seed speichern und alle änderungen abhängig von der Ursprungsversion.
War ein Planet mal Grün und hatte super viel ressourcen aber wurde mitlerweile runter gewirtschaftet, dann wird der Zustand als Patch im Savegame hinterlegt.
Des weiteren werden einige Dinge mit dem Savegame nicht gespeichert, bei RPG wie Diablo z.B. wurden per zufall alle Monster beim neuladen gesetzt, Schalter und Kisten waren in Defaultstellung und nicht über ein Savegame geregelt.
In einem Shooter z.B. können alle schon getöteten Monster per 1Bit als tot gespeichert werden und der rest wird garnicht gespeichert und ist dann wieder in default Modus. Für Monster im gleichen Abschnitt kann man z.B. die Daten genauer gespeichert(position, leben, ki zustand).
Man muss halt die Daten in der Simulationen prioritäten zuordnen und dementsprechend dann abstriche machen.
Ich würde das ganze in jeweils eine sqlite Datei packen, daneben noch Datein mit spezielle Daten(z.B. Screenshot vom Savegame, XML mit titel, uhrzeit, spieldauer, alles was interessant ist und wozu man nicht erst die große db file öffnen muss) und alles in ein tar.gz packen, was dann halt mit Endung sav abgelegt wird.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
ok... Damit ist im prinzip mein vielversprechendster Ansatz doppelt bekräftigt. Octree-Ähnliche Strukturen für die Laufzeit, TarGz fürs Speichern. Wunderbar . Dazu ein Zufallsalgo mit gleichen Werten bei gleichem Seed... Klingt nach einem leckeren Eintopf O.o
Danke für die Anregungen
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.