Große Tilemap



  • Unistyle schrieb:

    Also ein Grid besteht bereits.

    Ließ nochmal die Posts. Wir meinen ein anderes Grid. Stell dir vor, du legst ein weiteres, gröberes Gitter über deine Map, welches nun 32x32 diner Gridzellen umfasst.

    Es sind auch definitiv mehr als 2 Layer pro Etage möglich:
    http://dc469.4shared.com/img/ZZ5pXZLK/s7/exemplo.PNG

    Ich sehe keine Layer.Ich sehe unbegehbares Terrain und begehbares Terrain welches mit der Textur "treppe" markiert ist.



  • @hustbaer
    Achso, das wusste ich nicht. Man lernt immer weiter aus 🙂
    Ich ging davon aus, dass wenn man die Kamera an einen anderen Ort bringt, dass zumindest ein wenig speicher freigegeben wird, aber der reservierte Speicher bleibt genau gleich. Aber da hab ich mich wohl geirrt.

    Die Fragen kann ich gerne beantworten:

    1. Der Map Editor speichert die map lokal.
    2. Die Level Datei von Tibia ist 93~MB groß. (Es gibt Leute die haben "fast" die ganze map erkundet und diese mit Hilfe eines Programmes als map Datei zusammen"getracked") daher hab ich den Wert falls jemand fragt :p
    3. Wenn die map leer ist sieht man nur einen schwarzen Hintergrund (1kb map file)
    4. Die Hauptebene (Oberfläche der Erde sozusagen) ist schätzungsweise zu 80% belegt. Unterirdisch würde ich sagen sind es um die 50%. Überirdisch dürfte es am wenigsten sein, da es meist nur teile von Häusern sind und Höchstens einige Gebirge -> 30%~

    @otze
    Ach so meinst du das, aber in wie weit kann mir das helfen?

    Ich habe kein besseres Bild auf die schnelle finden können. Das mit dem Layer muss man so sehen: Auf eine Etage können viele Tiles übereinander liegen wie z.B. Terrain -> Tepich -> Tisch -> Buch.

    Edit: Ich muss mich bei euch entschuldigen... Aus früheren Foren Diskussionen bin ich davon ausgegangen, dass die Tibia map 32k*32k groß ist. Nachdem ich ein wenig herumprobiert habe um die Fragen von hustbaer zu beantworten habe ich etwas herausgefunden. Und zwar habe ich die Tibia map geöffnet und habe verzweifelt nach dem Inhalt gesucht.

    Ich habe folgendes festgestellt:
    Die Größe der Map ansich ist schon 32k*32k. Allerdings ist in der Nähe der Postion von 0/0 eine kleine Insel (Nur für die GameMaster/Support) und die eigentliche Spielkarte reicht von 29k/29k bis 32k/32k. Also sind eigentlich nur eine Fläche von 3k*3k wirklich belegt. Diese Größe habe ich dann sofort mal in meinem Programm festgelegt und es wird fast 2GB ram dabei reserviert.
    Gibt es eine Möglichkeit den Speicher nur für gesetzte Tile zu reservieren?
    Der fertige Map Editor den ich mir angeschaut habe tut dies ja anscheinend und kommt bei einer gefüllten Fläche auf knapp die Hälfte.

    Tut mir nochmals aufrichtig Leid für dieses missverständnis.. und wenn euch das hier langsam zu viel wird kann ich das verstehen 😞



  • Das ändert alles überhaupt nichts, alle Antworten sind nach wie vor gültig. Du solltest mittlerweile in der Lage sein das alles problemlos zu implementieren.



  • Da hast du Recht. Ich setz mich dann nun dran es fertig zu stellen und melde mich wieder. Danke soweit für eure Hilfe 🙂



  • Bei so großen Maps ist es ja ansich zwingend notwendig, die Karte in kleinere Abschnitte aufzuteilen.

    Wie hier schon mal jemand geschrieben hat:
    Du hast z.B. einzelne 100x100 Tiles große Karten-Stücke. Die eigentliche Map hat dann nur noch Referenzen auf diese Kartenstücke. Auf diese weise kannst du leere Abschnitte auch einfach leer lassen, ohne daß sie größere Mengen Speicher verbrauchen.
    Das ganze lässt sich auch tiefer verschachteln. Das Basis-Element ist ein Tile. 100x100 Tiles ergeben ein Kartenstück. 100x100 von diesen Kartenstücken ergeben die nächste Ebene, usw. bis man bei der Map als höchste Ebene angekommen ist (ich glaube das war das Grid das weiter oben gemeint war?)

    So kannst du recht einfach bestimmen, in welchem Kartenabschnitt sich ein Spieler gerade befindet, und kannst nur die Kartenstücke laden, die gerade im Sichtbereich des Spielers sind. Das Nachladen einzelner Stücke sollte relativ schnell gehen, da die einzelnen Stücke ja recht klein sind, und man kann das Laden ggf ncoh in einen Thread auslagern, damit der Spieler möglichst nichts davon merkt. Die einzelnen Abschnitte können dann zusätzlich noch gezippt oder mit einem anderen Algorithmus gepackt werden.
    Man kann auch zu jedem einzelnen Abschnitt eine Prüfsumme berechnen. Betritt der Spieler einen neuen Abschnitt, kann der Client eine Anfrage an den Server stellen, ob sich dieser Abschnitt seit dem letzten Betreten verändert hat, indem die Prüfsumme verglichen wird. So kann man vermeiden die Karte unnötig oft vom Server nachzuladen.

    Daß sich die Karte im Lauf der Zeit ändert sollte man in jedem Fall mit einplanen. Auch wenn 100MB nicht viel klingen - wenn 100 Spieler sich nach einem Update einloggen und die neue Karte ziehen sind das schonmal 10GB, von denen man viel hätte einsparen können.
    Andere Szenarios die man bedenken sollte ist auch, wie die Map bei den Entwicklern gespeichert wird. Ggf sollen ja auch mehrere Entwickler an der Map arbeiten, ohne sich gegenseitig auf die Füße zu treten. Das geht kaum, wenn die Map nur aus einer einzigen, riesigen Datei besteht. Teilt man die Map auf, kann zumindest ein Entwickler Kontinent A und der andere Kontinent B aufbauen.
    Das Datenformat sollte auch erlauben, daß die Map über Versionierungssysteme (Mercurial, Subversion, git, ...) verwaltet und von mehreren Entwicklern gleichzeitig bearbeitet werden kann, ohne daß beim Merge regelmäßig die Datei zerschossen wird oder Änderungen verloren gehen.
    Dazu kann die Map auf verschiedene kleine Dateien aufgeteilt werden. Auch ein text-basiertes Format wäre (trotz der Größe) eine Überlegung wert. Das Dateiformat das die Entwickler verwenden muss ja nicht das selbe sein, das dann an die Clients geschickt wird.
    Selbst wenn du alleine an dem Projekt arbeitest, bläht eine einzelne riesige Binär-Datei nur unnötig das Repository auf.



  • Unistyle schrieb:

    Edit: Ich muss mich bei euch entschuldigen...

    Ne, musst du nicht, ist ja nix schlimmes passiert 🙂

    Also sind eigentlich nur eine Fläche von 3k*3k wirklich belegt. Diese Größe habe ich dann sofort mal in meinem Programm festgelegt und es wird fast 2GB ram dabei reserviert.
    Gibt es eine Möglichkeit den Speicher nur für gesetzte Tile zu reservieren?
    Der fertige Map Editor den ich mir angeschaut habe tut dies ja anscheinend und kommt bei einer gefüllten Fläche auf knapp die Hälfte.

    Wurde im Prinzip schon beschrieben, aber nochmal konkreter:
    Du fasst z.B. 256x256 Tiles zu einem Block zusammen. Für eine 32K*32K Welt brauchst du dann 128*128 solche Blöcke.
    Also machst du ein 128128 Array aus Zeigern auf solche Blöcke.
    Einträge wo ein komplett leerer Block wäre sind dabei einfach "leer" (Nullzeiger).
    Und für Stellen wo nicht alles leer ist erzeugst du einen Block und speicherst den Zeiger auf diesen Block in dem 128
    128 Array.

    Jeder Block ist dann wieder ein Array mit 256*256 Einträgen. Ein Eintrag muss dabei dann nicht immer aus 14*3 Grafiknummern bestehen, auch hier kann man wieder optimieren.
    z.B. kann jeder Eintrag wieder ein Zeiger auf ein Array sein (der dann auch wieder Null ist, wenn in dieser Zelle gar nichts ist). Das Array kann dabei z.B. einfach so aufgebaut sein (1 Zeile ist ein Byte):

    Etagennummer A + 192
    High-Byte Grafiknummer A Layer 0
    Low-Byte Grafiknummer A Layer 0
    High-Byte Grafiknummer A Layer 1
    Low-Byte Grafiknummer A Layer 1
    High-Byte Grafiknummer A Layer 2
    Low-Byte Grafiknummer A Layer 2
    High-Byte Grafiknummer A Layer 3
    Low-Byte Grafiknummer A Layer 3
    ...
    Etagennummer B + 192
    High-Byte Grafiknummer B Layer 0
    Low-Byte Grafiknummer B Layer 0
    High-Byte Grafiknummer B Layer 1
    Low-Byte Grafiknummer B Layer 1
    ...
    Etagennummer C + 192
    ...
    ...
    255
    

    Das Array fängt also immer mit einer Etagennummer + 192 an.
    Dann kommen zwei Byte für eine Grafiknummer. Ob das nächste Byte eine Etagennummer oder das High-Byte einer Grafiknummer ist kannst du daran erkennen ob es >= 192 ist. Bzw. 255 für die "Ende" Markierung. Damit kannst du 49152 Grafiknummern abbilden (192*256) und 63 Etagennummern (255-192).
    Und als Abschluss kommt am Ende eine 255 statt der Etagennummer.

    Für eine Zelle mit nur einer Grafik #23 in Etage 1 brauchst du dann 4 Byte: 193, 0, 23, 255.

    Wenn du wesentlich mehr Grafiknummern brauchst kannst du auch 3 Byte statt 2 verwenden.

    Eine andere Möglichkeit wäre pro Block ein fixes Array mit 256*256 Feldern und 42 (bzw. wie viel du halt braucht) Layern, also 256*256*42*2 = 5,25 MB (2 = 2 Byte pro Grafiknummer). So hältst du aber nur die Blöcke im RAM die gerade angesehen werden. Blöcke die gerade nicht gebraucht werden komprimierst du einfach mit RLE.
    RLE ist super einfach zu implementieren und läuft auch recht schnell - sollte keine schlimme Verzögerung geben selbst wenn man schnell in der Map rumscrollt. Und falls doch kannst du immer noch mit der Blockgrösse runtergehen und dafür mehr Blöcke machen.

    Auf Disk speicherst du das ganze dann natürlich auch RLE komprimiert.

    Das sind jetzt nur zwei von vielen vielen Möglichkeiten wie man sowas machen kann. Überleg dir selbst noch ein paar weitere, schreib dir Pro und Contra Listen. Und dann nimmst du die Lösung die am einfachsten umzusetzen ist 😉


Anmelden zum Antworten