Große Datenmängen (Map) speichern

  • VB.NET

Es gibt 28 Antworten in diesem Thema. Der letzte Beitrag () ist von Chris96.

    Große Datenmängen (Map) speichern

    Hey Leute,
    Ich programmiere zurzeit ein kleines Spiel. Man ist ein Bergarbeiter und gräbt sich durch die Erde :D.
    Ich speichere die Werte eines Blockes in einen 2-dimensionalen array(10000,10000). Nun möchte ich die Positionen der Blöcke etc. speichern, das wären aber im Extremfall 100000000 Koordinaten mit Werten.

    Hat jemand eine Idee wie man eine solche Datenmenge schnell speichern kann ?
    Ich habe es bereits mit einer Text-Datei probiert, jedoch ist die Speicherdauer extrem Lange.

    Mit Datenbanken habe ich keine Erfahrung weshalb ich auch nicht weiß welche geeignet wäre.

    Danke im Voraus :)
    Wenn es sich um eine tile-basierte Map handelt, dann kannst du einfach eine Palette an Tiles erstellen und dann ins Array die Indizes schreiben anstatt die ganzen Tile-Informationen.
    So speicherst du jedes Tile einmal und dann nur eine Zahl pro Feld.

    Ansonsten wird nicht ganz klar, wie dein Spiel aufgebaut ist.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Counterbug“ ()

    Wie speicherst du denn aktuell und wie viele verschiedene Werte kann ein Feld haben?

    //EDIT:
    @backtothetoast
    Höchstens "manuelle" Serialisierung würde hier was helfen. Die "normale" würde warscheinlich viiiiel größere Dateien erzeugen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nafets3646“ ()

    Du musst das Spielfeld in kleinere Abschnitte unterteilen und nur diejenigen laden und speichern, bei denen es nötig ist, ansonsten füllst du deinen Arbeitsspeicher enorm zu (alleine die Pointer im Array brauchen schon 400MB :!: , mit den zugehörigen Klassen bist du da schnell in Bereichen, die selbst die besten Highend-PCs nicht mehr tragen können).
    Also das ganze Spiel ist aufgebaut wie die App Gem Miner (Siehe Bild).


    Der Spieler gräbt sich also durch die Erde, ganz einfach gehalten in 2D und ohne XNA etc.
    Ich speichere im Array zahlen von 1-20 für verschiedene Sachen/Gegenstände beispielsweise eine Leiter besitzt den Wert 1.


    Im Form Paint Sub Überprüfe ich dann welche Spielfelder (Ein Feld ist 40*40px groß) aktuell sichtbar sind, um nicht alles Zeichnen zu müssen.
    Danach gucke ich welche Zahl in der Koordinate/in dem Feld steckt und zeichne dann, wenn es z.B. 1 wäre, eine Textur für eine Leiter in das entsprechende Feld.


    Da mein Array 10000*10000 groß ist kann der Spieler 100000000 Blöcke weg graben. Gehen wir nun davon aus das es ein Spieler schaft jeden Block zu entfernen, dann müssten 100000000 Einträge abgespeichert werden, jeder mit dem Inhalt, Beispielsweise 4, für ein Leeres Feld.


    @Counterbug ich benutze ja bereits dieses Prinzip aber das bringt mir bei 100000000 Zeichen leider nichts.
    @backtothetoast von Serialisierung hab ich bis jetzt noch nie was gehört, ich werde es mir in den nächsten Tagen mal genauer anschauen.
    @Artentus ich würde natürlich auch nur die entsprechenden Teile der Map laden/generieren. Jedoch müssten wenn ein Spieler alle Felder leer gräbt trotzdem 100000000 Informationen gespeichert werden.
    @Andy16823 wie man es nimmt, wenn dann ein sehr sehr unrealistischer 2D Simulator, also eher nein :D
    @nafets3646 Aktuell würde ich gucken wie viele Felder der Spieler gesehen hat und diese dann in einer .txt speichern. Bei 100000000 gesehenen Felder(Auch wenn das wahrscheinlich nicht vorkommen wird) ist die Speicherzeit aber nicht ansatzweise aushaltbar.

    Danke schon mal für eure Antworten :)



    Das ist auf jeden Fall nicht zumutbar, wir sprechen hier von Speicherbelegungen im dreistelligen Gigabyte-Bereich. Du wirst dir da wohl oder übel was anderes einfallen lassen müssen, Stacks aus mehreren Blöcken oder so, das, was du da vorhast, wird nicht laufen.
    @00yoshi
    Wat? Was du da rechnest, ergibt überhaupt keinen Sinn.
    Es sind 100.000.000 Elemente. Wären es alles Bytes, dann entspräche das exakt 100MB. Es sind aber vermutlich Pointer auf Klassen, welche auf 32Bit-Systemen 4Byte und auf 64Bit-Systemen 8Byte groß sind. Bei 32Bit macht das dann 100.000.000 * 4 = 400MB und bei 64Bit sind es 100.000.000 * 8 = 800MB. Hinter jedem Pointer liegt aber noch ne Klasse, und wenn die auch nur 100 Byte groß wäre, dann sind wir schon bei 10GB.
    Ich werde die Map einfach kleiner machen und nur wirklich vom Spieler gesehene Teile speichern, der Rest wird dann zufällig nach generiert. Damit sollte es dann in Akzeptabler Geschwindigkeit funktionieren und die gespeicherte Datei auch nicht allzu groß werden.

    Die Werte würden auch leider nicht im Byte bereich liegen.

    Trotzdem Danke für eure Antworten :)
    Das mit den Chunks wäre wahrscheinlich die beste Lösung, da das aber mein erstes Spiel ist und ich jetzt kein Profi in VB bin, halte ich das speichern möglichst einfach.
    Ich hab die Map jetzt entsprechend verkleinert, so das die Speicherzeit sehr gering ist.

    Wenn ich nochmal ein Spiel scripte dann werde ich auch die Chunks-Methode verwenden.

    Danke, für eure Antworten :)
    Das glaub ich auch :D
    Hier der Aktuelle Code zum speichern:


    Variablen:

    VB.NET-Quellcode

    1. Public Seen_LST As New List(Of String) 'Liste aller gesehenen Blöcke
    2. Public _Save_String As String = "" 'Finale Datei
    3. Dim Field_Size As New Size(500, 1000) 'Feldgröße
    4. Public Field(Field_Size.Width, Field_Size.Height) As Integer 'Feld Array
    5. Public MapX As Integer = 250 'Horizontale Verschiebung der Map (Für Bewegung)
    6. Public MapY As Integer = 0 'Vertikale Verschiebung der Map (Für Bewegung)



    Backgroundworker (Alle gesehenen Blöcke werden in Seen_LST hinzugefügt, danach wird _Save_String die Koordinaten+Inhalt hinzugefügt. Wird bei jeder Spieler/Map Bewegung gestartet):


    VB.NET-Quellcode

    1. Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    2. For y = 0 To 16 'Sichtbares Spielfeld (Höhe)
    3. For x = 0 To 24 'Sichtbares Spielfeld (Breite)
    4. Dim X_C As Integer = x + MapX 'Koordinate X + Verschiebung der Map
    5. Dim Y_C As Integer = y + MapY 'Koordinate Y + Verschiebung der Map
    6. Dim CP As String = X_C & " " & Y_C 'Beide werte zusammenfügen
    7. Seen_LST.Add(CP) 'Zur liste der gesehenen Koordinaten hinzufügen
    8. Next
    9. Next
    10. Seen_LST = DeleteDoublicates(Of String)(Seen_LST) 'Doppelte Koordinaten Einträge löschen
    11. _Save_String = "" 'Inhalt aus _Save_String löschen
    12. Dim Text As String
    13. Dim Pos As Long
    14. Dim x_var As Integer = 0
    15. Dim y_var As Integer = 0
    16. For z As Integer = 0 To Seen_LST.Count - 1 'Alle gesehnen Blöcke durchschleifen
    17. Text = Seen_LST(z)
    18. Pos = InStr(1, Text, " ") 'Erste Koordinate ermitteln
    19. x_var = CInt(Mid(Text, 1, Pos)) 'Erste Koordinate ermitteln
    20. Pos = InStr(1, Text, " ") + Len(" ") 'Zweite Koordinate ermitteln
    21. y_var = CInt(Mid(Text, Pos, Text.Length)) 'Zweite Koordinate ermitteln
    22. _Save_String = _Save_String & ";" & (x_var & " " & y_var & "=" & Field(x_var, y_var)) 'Die Koordinaten+Inhalt direkt in _Save_String speichern
    23. Next
    24. End Sub



    der eigentliche Code zum speichern ist dann nur noch:


    VB.NET-Quellcode

    1. System.IO.File.WriteAllText("MapS.txt", _Save_String)



    Eine gespeicherte Datei sieht dann z.B. so aus:

    Spoiler anzeigen

    Quellcode

    1. ;250 1=5;251 1=5;252 1=5;253 1=5;254 1=5;255 1=5;256 1=5;257 1=5;258 1=5;259 1=5;260 1=5;261 1=5;262 1=5;263 1=5;264 1=5;265 1=5;266 1=5;267 1=5;268 1=5;269 1=5;270 1=5;271 1=5;272 1=5;273 1=5;274 1=5;250 2=5;251 2=5;252 2=5;253 2=5;254 2=5;255 2=5;256 2=5;257 2=5;258 2=5;259 2=5;260 2=5;261 2=5;262 2=5;263 2=5;264 2=5;265 2=5;266 2=5;267 2=5;268 2=5;269 2=5;270 2=5;271 2=5;272 2=5;273 2=5;274 2=5;250 3=5;251 3=5;252 3=5;253 3=5;254 3=5;255 3=5;256 3=5;257 3=5;258 3=5;259 3=5;260 3=5;261 3=5;262 3=5;263 3=5;264 3=5;265 3=5;266 3=5;267 3=5;268 3=5;269 3=5;270 3=5;271 3=5;272 3=5;273 3=5;274 3=5;250 4=5;251 4=5;252 4=5;253 4=5;254 4=5;255 4=5;256 4=5;257 4=5;258 4=5;259 4=5;260 4=5;261 4=5;262 4=5;263 4=5;264 4=5;265 4=5;266 4=5;267 4=5;268 4=5;269 4=5;270 4=5;271 4=5;272 4=5;273 4=5;274 4=5;250 5=5;251 5=5;252 5=5;253 5=5;254 5=5;255 5=5;256 5=5;257 5=5;258 5=5;259 5=5;260 5=5;261 5=5;262 5=5;263 5=5;264 5=5;265 5=5;266 5=5;267 5=5;268 5=5;269 5=5;270 5=5;271 5=5;272 5=5;273 5=5;274 5=5;250 6=5;251 6=5;252 6=5;253 6=5;254 6=5;255 6=5;256 6=5;257 6=5;258 6=5;259 6=5;260 6=5;261 6=5;262 6=5;263 6=5;264 6=5;265 6=5;266 6=5;267 6=5;268 6=5;269 6=5;270 6=5;271 6=5;272 6=5;273 6=5;274 6=5;250 7=5;251 7=5;252 7=5;253 7=5;254 7=5;255 7=5;256 7=5;257 7=5;258 7=5;259 7=5;260 7=5;261 7=5;262 7=5;263 7=5;264 7=5;265 7=5;266 7=5;267 7=5;268 7=5;269 7=5;270 7=5;271 7=5;272 7=5;273 7=5;274 7=5;250 8=5;251 8=5;252 8=5;253 8=5;254 8=5;255 8=5;256 8=5;257 8=5;258 8=5;259 8=5;260 8=5;261 8=5;262 8=5;263 8=5;264 8=5;265 8=5;266 8=5;267 8=5;268 8=5;269 8=5;270 8=5;271 8=5;272 8=5;273 8=5;274 8=5;250 9=4;251 9=4;252 9=4;253 9=4;254 9=4;255 9=4;256 9=4;257 9=4;258 9=4;259 9=4;260 9=4;261 9=4;262 9=99;263 9=4;264 9=4;265 9=4;266 9=4;267 9=4;268 9=4;269 9=4;270 9=4;271 9=4;272 9=4;273 9=4;274 9=4;250 10=2;251 10=2;252 10=2;253 10=2;254 10=2;255 10=2;256 10=2;257 10=2;258 10=2;259 10=2;260 10=2;261 10=2;262 10=99;263 10=2;264 10=2;265 10=2;266 10=2;267 10=2;268 10=2;269 10=2;270 10=2;271 10=2;272 10=2;273 10=2;274 10=2;250 11=2;251 11=2;252 11=2;253 11=2;254 11=2;255 11=2;256 11=2;257 11=2;258 11=2;259 11=2;260 11=2;261 11=2;262 11=99;263 11=99;264 11=99;265 11=6;266 11=2;267 11=2;268 11=2;269 11=2;270 11=2;271 11=2;272 11=2;273 11=2;274 11=2;250 12=2;251 12=2;252 12=2;253 12=2;254 12=2;255 12=2;256 12=2;257 12=2;258 12=2;259 12=2;260 12=2;261 12=2;262 12=6;263 12=6;264 12=99;265 12=2;266 12=2;267 12=2;268 12=2;269 12=2;270 12=2;271 12=2;272 12=2;273 12=2;274 12=2;250 13=2;251 13=2;252 13=2;253 13=7;254 13=7;255 13=2;256 13=2;257 13=2;258 13=2;259 13=2;260 13=2;261 13=2;262 13=2;263 13=7;264 13=99;265 13=2;266 13=2;267 13=2;268 13=2;269 13=2;270 13=2;271 13=2;272 13=7;273 13=2;274 13=2;250 14=2;251 14=2;252 14=2;253 14=2;254 14=2;255 14=2;256 14=2;257 14=2;258 14=2;259 14=2;260 14=2;261 14=2;262 14=7;263 14=2;264 14=99;265 14=2;266 14=7;267 14=7;268 14=2;269 14=2;270 14=2;271 14=2;272 14=2;273 14=2;274 14=7;250 15=2;251 15=2;252 15=2;253 15=7;254 15=7;255 15=2;256 15=7;257 15=2;258 15=2;259 15=2;260 15=2;261 15=2;262 15=2;263 15=2;264 15=99;265 15=2;266 15=2;267 15=2;268 15=2;269 15=7;270 15=2;271 15=2;272 15=2;273 15=2;





    Sorry für die schlechte Formatierung/Einrückung, ging irgendwie nicht besser :)
    Mal ein paar Punkte, wie du es verbessern könntest:
    -Anstatt die Stringe mit dem &-Operator zu verbinden, nutze einen StringBuilder, der ist schneller
    -Für was die Koordinaten der einzelnen Felder speichern? Du brauchst nur die Startkoordinate, den Rest kannste dir berechnen
    -Arbeite auf der Byte-Ebene anstatt mit Strings, da haste in einem Zeichen in deiner Datei entweder 2 Felder a 16 Möglichkeiten oder 1 Feld mit 256 Möglichkeiten. Bei der zweiten Variante hast du also 1 Byte pro Feld, wobei du für jedes Feld 256 Möglichkeiten speichern kannst -> viel weniger Speicherplatzverbrauch.