Das könnte mal ein Spiel werden...

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von ThuCommix.

    Das könnte mal ein Spiel werden...

    Hey

    Ich möchte euch mal die Arbeit der letzten paar Stunden von mir präsentieren, ich möchte eine art RPG Spiel programmiert, der Typ soll angelehnt sein an Vampire Dawn, falls das noch jemanden was sagt. Ich habe mich zuerst mit den Mapsystem beschäftigt.
    Die einzelnen Tiles haben zwei Sprites, das jeweils letztere wird über das erste gezeichnet, um z.B auf ein Gras-Tile einen Baum oder sonstiges zu zeichnen, auch gibt es schon erste Events.
    Was sind Tile Events? Die Handlung des Spiels wird komplett durch die MapFile bestimmt, indem sie in bestimmten Tiles die Information hinterlässt, eine Nachricht einzublenden, oder eine neue Map zu laden. Natürlich funktioniert die Levelabgrenzung und Kollisionserkennung der Tiles, diese können jeweils auch selbst bestimmt werden.

    Auschnitt aus der Mapfile:

    Quellcode

    1. grastype1;grastype1;1;None<>|grastype1;grastype1;1;None<>|grastype1;grastype1;1;None<>|grastype1;grastype1;1;None<>|sand;sand;1;Message<Hey just walked on sand!>


    Momentan gibt es erst ein richtiges Event (Message) läuft der Spieler über dieses Tile, wird eine Nachricht eingeblendet. Falls man ein None Tile eine Message mitgegeben hat (None<Description>) wird diese eingeblendet, wenn der Spieler in Richtung des Tiles schaut, und Space drückt.



    Warum ich diesen Thread eröffnet habe:

    Ich möchte hauptsächlich Anregungen von euch bekommen, was ich noch einbauen sollte, oder wie ich Vorgänge optimieren soll.


    Natürlich gibts für euch auch etwas zum Testen...



    Was hat sich getan? #1

    Ich zeichne nun Direkt auf eine Form und nicht mehr auf eine PictureBox, performence Geschwindigkeit bringt das leider nicht.. Auch die Dialoge habe ich ein bischen aufgewertet, wie ihr später auf den Screenshots sehen werden, auch ein Pause Menü ist jetzt mit Escape integriert. Desweiteren habe ich die Grundlage für Items geschaffen, es gibt folgende Abstrakte Klassen:

    Sword, Armour, Potion, CrapItem






    CrapItems sind nutzlose Items, die nur im Verkauf Geld bringen sollen.





    Was hat sich getan? #2

    Nun portet sich die Figur nicht mehr in das nächste Feld, sondern läuft ganz "smooth" auf das nächste Tile :) Du hattest recht Freak, mit meinen KeyInputSystem hat das nicht so funktioniert, musste da alles nochmal ein Stück umbauen.
    Dateien
    • enginetest.zip

      (20,72 kB, 119 mal heruntergeladen, zuletzt: )
    • enginetest.zip

      (25,05 kB, 91 mal heruntergeladen, zuletzt: )
    • enginetest.zip

      (25,95 kB, 84 mal heruntergeladen, zuletzt: )

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

    Morgen,

    ich find das ganze recht interessant.. Erinnert mich ganz entfernt schon an so einfache RPG - Maker etc. - Geschichten.

    Lauft auch unter Linux (find ich gut ^^). Ich fänds nicht schlecht wenn eine solche Engine, gerade wenn Sie per GDI läuft (also nicht mit Windows.Forms etc. zusammenhängt), auch auf Linux mittels Mono laufen würde.
    Jetzt schnell und einfach das Zehnfingersystem mit Scribble 3 erlernen. Mehr Informationen und Download gibts hier. Redundancy2 - leichtgewichtige freie Cloudsoftware. Folge mir auf GitHub

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

    Hey, ich habe mal einen richtig guten Artikel über ein Pokemonspiel mit dem RPG-Maker XP gelesen. Nicht gleich abschrecken lassen, der Typ hat wirklich was drauf gehabt und sich nicht nur was zusammengeklickt^^ Habe leider keinen Link zu dem Artikel, darum erzähl ich einfach mal:

    Es gab mehrere Mapausschnitte die zusammen die gesamtmap ergeben. NPCs konnten so nur in ihrem Map-Bereich existieren, was aber auch gut war denn in Pokemon interessiert der NPC fünf Dörfer weiter nicht - die Rechenlast kann man sich sparen. Verknüpft waren die Karten (nicht nur die einzelnen Bereiche, auch die Häuser) durch Teleport-Einträge in einer Datei, die nur für den aktuellen Bereich gültig ist. Vorteil: Ebenfalls interessiert der Hauseingang fünf Dörfer weiter nicht und es muss nur eine minimale Anzahl abgefragt werden. Die Einträge in der Teleport-Datei haben informationen wie Blickrichtung, Position und KartenID enthalten.
    Es gab eigentlich für alles eine eigene Listen-Datei, für die Gebiete in denen man Pokemon antreffen konnte gab es eine spezielle Datei, für jeden Bereich gibt es eine (darf man Fahrrad fahren? Hintergrundmusik, etc).
    Großer Vorteil von vielen Dateien ist, dass man sehr leicht erweitern kann und alles übersichtlich bleibt da man sehr gezielt nach den benötigten Infos suchen/debuggen kann. Nachteil ist eben, dass es viele Dateien gibt, aber als zip sollte das kein Problem darstellen.

    Die Tiles hatten auch allerlei Informationen: Kollision (erweitert, man könnte es als "Begehbarkeit" bezeichnen da die Gehrichtung eine Rolle spielt. so kann man die Hänge beispielsweise herunterspringen aber nicht hochklettern), Texur und TerrainID (sehr nützlich um z.B. Surfer/Bootfahren zu realisieren - prüfen ob das nebenfeld wasser ist, wenn ja, dann kann los geschiffert werden. Kann/Sollte desshalb mit in die Kollisionsprüfung einfließen). Es gibt also wieder eine Liste, die auskunft darüber gibt wie ein Tile auszusehen hat und welche Eigenschaften es hat. Die Map besteht dann nur noch aus TileIDs und ggf ein paar Zusatzinfos (erzwungene Kollision etc).

    Ich denke mal ein solches System würde sich viel leichter warten lassen und bleibt sehr übersichtlich. All diese Infos in jedes Tile zu hinterlegen würde zwar auch funktionieren, dann hast du aber später (wenn du vllt einen Editor programmierst) viel Arbeit um einfachste Probleme zu lösen: Vereinfacht gesagt ist ein Fangebiet ein Rectangle, ein Eintrag und das Fangebiet ist da oder wieder gelöscht. Du müsstest jede Information (welches Gebiet? Welche Pokemon laufen da rum?) jedem Tile zuweisen... viel arbeit, schwer zu warten und aktuell zu halten.

    Tipp von mir um das Sprunghafte gehen in den Griff zu bekommen:
    In meiner 2.5D Engine (die ja streng genommen auch auf einer 2D tilebasierenden Welt basiert) speichere ich Positionen als PointF (also x und y angaben als Single statt Integer). So sind zwischenschritte ganz einfach möglich: 2.34 ; 1.9 bedeutet dann, dass man sich auf Tile 2;1 befindet (=> math.ceiling benutzen) und um 0.34 Einheiten nach rechts und 0.9 Einheiten nach unten verschoben ist. Eine Einheit ist dabei das Kantenmaß des (quadratischen) Tiles in Pixeln. Schon kann man kreuz und quer herumlaufen (zwar nicht exakt wie in Vampires Dawn aber ich denke mal das tut der Sache keinen Abbruch).
    Das du die Zeichenzeit mit angibts zeigt, dass du schon auf dem richtigen Weg bist. Der Gameloop läuft ja in etwa so ab:

    do
    Update (neue Positionen berechnen etc)
    Zeichnen
    ggf ausbremsen um z.b. eine konstante Framerate von 50 zu erhalten
    loop

    nun könntest du mittels Stopwatch die zeit die seit dem Letzten update vergangen ist messen und den loop gezielt ausbremsen. Die vergangene Zeit (die entweder konstant ist oder mal steigt, da die Framerate performancebedingt abfällt) übergibts du dem Update-Sub und ermöglichst so, dass sich alle NPCs (und animierten Vorgänge) immer (also unabhängig von der Framerate) gleichschnell abspielen.
    Die Berechnungen sind so auch sehr einfach zu machen, schau einfach mal hier: [VB 2010] Auto fahren mit Richtung

    so genug geschrieben xD
    gn8 und viel spass beim weiterentwickeln! Ich hoffe den ein oder anderen Gedanken kann man brauchen^^
    lg

    Edit: Warum steigt die Zeichenzeit (am anfang = 3ms) linear auf ca. 20ms wenn man nach rechts unten geht? xDD
    Edit2: CreateGrahpics?

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

    Ich geh erstmal nur auf deine Edits ein:

    Edit: Warum steigt die Zeichenzeit (am anfang = 3ms) linear auf ca. 20ms wenn man nach rechts unten geht? xDD


    Es gibt keine UpdateLoop, es werden nur Bereiche neu gezeichnet, welche sich verändern (Keine Bewegung, keine Veränerung). Ich Update nur zwei Bereiche, das Tile wo der Char früher stand, und die neue Position.
    Kinsi meinte bereits, dass das mit NPC dann schwierig werden könnte, aber ich kann ja auch einfach ihre Bewegung berechnen, und dann die Bereiche Invaliden?

    Edit2: CreateGrahpics?


    Paint Event der Form

    Zu dem laufen:

    (Gott sei dank kennst du Vampire Dawn) Werden in VD die Bewegung nicht auch Sprunghaft gemacht? In meiner Erinnerung läuft man da auch in Rechteckigen Tiles ;o
    Ich werde aber mal gucken wie genau ich das mit den laufen umsetze.


    Kannst du mich mit der Updateloop aufklären, ist das einfach ein Timer, der alle 60ms, alles Invalidet?
    Kannst du mich mit der Updateloop aufklären, ist das einfach ein Timer, der alle 60ms, alles Invalidet?


    jein, das ist eine schleife, welche versucht auf 60 fps zu kommen, dafuer musst du die zeit messen die beim zeichnen vergeht, und nach dem zeichnen den thread so lange warten dassen, dass zeichnen + warten 16 ms gedauert haben. wenn das zeichnen halt >16 ms gedauert hat geht das ncht, dann lässt du das warten halt weg.
    Hi
    VD ist ja mit dem RPG Maker gemacht und es ist ja üblich, dass man genau wie bei dir von Tile zu Tile geht - es werden allerdings ein paar zwischenschritte gemacht damit es wie eine Bewegung aussieht.
    Dein Zeichnen-System hat noch einen weiteren Nachteil: spätestens wenn es einen bewegten Bildausschnitt gibt (die Map wird ja denke ich größer werden als es der Bildschirm anzeigen kann - darum immer nur ein kleiner Ausschnitt sichtbar und die Spielerfigur in der Mitte) muss ja nach jedem neuberechnen der Positionen bzw wenn sich auch nur der Spieler ein wenig bewegt ALLES neugezeichnet werden. Ist also kein Performancegewinn, ein Spiel sollte eine konstante Framerate haben, dann hat man die wenigsten Probleme.

    Kinsi wird da glaubeich eine etwas andere Meinung vertreten aber für einen Gameloop halte ich folgendes System für am sinnvollsten:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class GameLoopTicker
    2. Public Sub New()
    3. bgw.WorkerReportsProgress = True
    4. bgw.WorkerSupportsCancellation = True
    5. End Sub
    6. Public ZielFPS As Integer = 50
    7. Public AktuelleFramerate As Single = 0
    8. Public Event Update(ByVal tGameTime As Integer) 'Positionen Updaten (Kein Zugriff auf GUI!)
    9. Public Event UpdateGUI(ByVal tGameTime As Integer) 'GUI updaten (async)
    10. Public Event Render() 'Rendern
    11. WithEvents bgw As New System.ComponentModel.BackgroundWorker
    12. Public Sub Start()
    13. bgw.RunWorkerAsync()
    14. _shutDown = False
    15. End Sub
    16. Public Sub Beenden()
    17. _shutDown = True
    18. End Sub
    19. Dim _shutDown As Boolean = False
    20. Dim GameTime As Integer = 0
    21. Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
    22. Dim UpdateStopWatch As New Stopwatch
    23. Dim RenderStopWatch As New Stopwatch
    24. Do Until _shutDown
    25. 'Update
    26. UpdateStopWatch.Reset()
    27. UpdateStopWatch.Start()
    28. RaiseEvent Update(GameTime)
    29. UpdateStopWatch.Stop()
    30. GameTime = 0
    31. GameTime = CInt(UpdateStopWatch.ElapsedMilliseconds)
    32. 'Rendern
    33. RenderStopWatch.Reset()
    34. RenderStopWatch.Start()
    35. RaiseEvent Render()
    36. RenderStopWatch.Stop()
    37. GameTime += CInt(RenderStopWatch.ElapsedMilliseconds)
    38. 'GUI Updaten
    39. bgw.ReportProgress(1)
    40. 'ggf. ausbremsen
    41. Dim sleepTime As Integer = CInt(1000 / ZielFPS) - GameTime
    42. If sleepTime > 0 Then
    43. GameTime += sleepTime
    44. Threading.Thread.Sleep(sleepTime)
    45. End If
    46. AktuelleFramerate = CSng(1000 / GameTime)
    47. Loop
    48. End Sub
    49. Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
    50. If CInt(e.ProgressPercentage) = 1 Then
    51. RaiseEvent UpdateGUI(GameTime)
    52. End If
    53. End Sub
    54. End Class


    Verwendung:

    VB.NET-Quellcode

    1. WithEvents Ticker As New GameLoopTicker
    2. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    3. Ticker.ZielFPS = 1
    4. Ticker.Start()
    5. End Sub
    6. Dim tmpRender As Bitmap = Nothing
    7. Private Sub Ticker_Render() Handles Ticker.Render
    8. ''Zeichnet die aktuelle Szene anhand der gegebenen Informationen
    9. 'tmpRender = DeineGrafikEngine.RenderToBitmap
    10. 'Wichtig: von hier aus kein Zugriff auf die GUI, die Bitmap kann also noch nicht gezeichnet/angezeigt werden!
    11. End Sub
    12. Private Sub Ticker_Update(tGameTime As Integer) Handles Ticker.Update
    13. 'Positionen neu berechnen
    14. 'tgametime wird in ms angegeben: GameTimeInSekunden = tGameTime / 1000
    15. 'Wenn man nun mit Geschwindigkeiten für die Bewegungen arbeitet (der Spieler möge sich mit 2 Einheiten pro Sekunde bewegen
    16. 'wobei eine Einheit der Kantenlänge eines Tiles entspricht) statt iwelcher konstanter Werte hat man immer (egal welche Framerate)
    17. 'eine gleichmäßig schnell wirkende Bewegung
    18. 'XNeu = XAlt + Geschwindigkeit * Zeit * math.Cos(winkel)
    19. 'YNeu = YAlt + Geschwindigkeit * Zeit * Math.Sin(winkel)
    20. 'Wichtig: von hier aus kein Zugriff auf die GUI
    21. End Sub
    22. Private Sub Ticker_UpdateGUI(tGameTime As Integer) Handles Ticker.UpdateGUI
    23. ' PictureBox1.image = tmpRender
    24. Me.Text = Ticker.AktuelleFramerate.ToString("0.00") & " FPS"
    25. 'Hier kann auf die Gui zugegriffen werden
    26. End Sub


    Den Code kannst du gerne verwenden auch ohne auf mich zu verweisen^^


    Großer vorteil von meinem System: wenn sich der Spieler bewegt, wird sich bei jedem Frame (egal ob unter 20 FPS oder 60FPS) der Spieler:
    - gleichschnell Bewegen (+/- eine kleine Toleranz, da die Zeiten von ca. 20ms als Integer gehandhabt werden und ein Rundungsfehler da schon +/- 5% ausmacht)
    - in jedem(!) Frame wird der Spieler sich ein kleines Stück bewegen. Es gibt niemals Frames indenen keine Positionsveränderung festzustellen ist UND es werden nur soviele Updates (also Positionserneuerungen) durchgeführt wie nötig.

    Kinsi baut lieber auf 2 Threads auf - einer Zeichnet, der andere Updatet die Positionen ständig. Da hat man dann allerdings das Problem, dass:
    - mehr Updates gemacht werden als notwendig / oder weniger. Folge: Keine Positionsänderungen sichtbar bzw manche Updates gehen "ins leere" und werden letzen endes nicht sichtbar
    - der UpdateThread verändert die Daten während dem Zeichnen. Bei meiner Engine wurde dieser Effekt besonders bei geringen Frameraten sichtbar: Annahme: Man dreht sich. In der Zeichenroutine werden zuerst die Wände gezeichnet, dann Objekte. Ändert sich nun der Kamerawinkel während dem Zeichnen, passiert es, dass die Objekte unter einem anderen Blickwinkel gezeichnet werden wie die Wände - wirkt so als ob die Objekte nicht so richtig fest an ihrem Platz stehen würden xD

    diese Probleme entfallen bei meinem System komplett da Update und Render strikt nacheinander ausgeführt werden und nicht zwischendrin. Vorteil von Kinsi's System ist ein Performancegewinn. Sollte imo aber nicht so stark ins Gewicht fallen.

    lg
    @ Samus Aran
    warum? xD da bin ich anderer Meinung^^
    Wenn ich update 10 mal aufrufe und Draw dagegen nur einmal, dann sind 9 Updatevorgänge für die Katz, da sie ja nicht "sichtbar" werden. Da sich die Updatevorgänge ja eh nach der Zeit die seit dem letzten Update und Draw verstrichen ist richten, erhält man immer die passenden Ergebnisse.
    Wenn das System mit dem zeichnen nicht hinterher kommt wird die übergebene GameTime automatisch größer, die Sprünge der Figuren auch. Logisch, da man ja nur noch z.b. 10 Frames die Sekunde macht und die zwischenschritte nichtmehr erkennen kann..
    Nur weil die Dinge, die in der Update-Methode passieren, nicht sichtbar sind, sind sie nicht "für die Katz".
    Stell dir vor, das Spiel läuft mit 3 FPS. Bei dir wird Update() 3-mal pro Sekunde aufgerufen. Das heißt, dass Tastendrücke wie z.B. Escape nur 3-mal pro Sekunde registriert werden können, und deshalb oft nicht registriert werden. Und wenn die Knöpfe die Bewegung des Spielers steuern, ists noch schlimmer, da die Bewegung nur 3-mal pro Sekunde aktualisiert wird. Das wäre noch schlimmer als Lag wegen ner schlechten Internetverbindung.
    in einem spiel hatte ich dein system ja mal getestet, das probldm dabei ist dass du es nicht hinkriegen kannst, das es immer gleich schnell ist. des weiteren, wenn es nun sagen wkr mal nur 10 fps gibt, und dann ein spieler fällt, hast du ne hohe cance dass der apieler z.b. durch einen block durchclippt weil der spieler bei niedrigen framerates mehr bloecke pro cycle fällt und dadurch z.b. durch nen block durchfsllen kann. und ob es nun unsichtbare updates gibt(mein system) oder es per berechnung auf den wert gebracht wird, der gefallen wird(nicht genau moeglich) ist doch ziemlich egal.
    Ich möchte jetzt noch nicht mit XNA arbeiten, wenn GDI dafür auch noch aussreicht..

    @FreakJNS

    Ganz super, jetzt hab ich deinen Thread gelesen, nachdem ich mithilfe von Kinsi, den updateLoop gebaut habe :D

    Kinsi baut lieber auf 2 Threads auf - einer Zeichnet, der andere Updatet die Positionen ständig.


    Ersteres na klar, aber wieso benötigt man ein Update der Positionen? Ich reagiere auf KeyBoard Events, und und setze einfach die Location, für NPC oder so brauch ich dann erst ein Update Thread der Locs.

    Ansonsten muss ich zugeben, das ich deine geballten Informationen noch nicht sogut aufnehmen kann ;)
    @Samus Aran
    @kinsi

    verdammt, da habt ihr recht!

    Problem ist, dass beides nur ein ein Problem mit dem anderen vertauscht:
    - Update-Rate = FrameRate: bei geringen Frameraten Clipping und Tastenbugs
    - Update-Rate > FrameRate: bei geringen Frameraten Grafikfehler

    Wie könne man BEIDE Probleme (die ja auch nur bei sehr geringen Frameraten sichtbar werden) aus der Welt schaffen? Mein System wird da scheitern, die Kollisionsfehler könnte man noch herausrechnen (Pfad zwischen Punkt A und B prüfen) - spätestens wenn es um die Tastenauswertung geht wars das dann aber..

    Man müsste (wie kinsi auch schon lange sagt xD) die Mapdaten extra für den Zeichenvorgang clonen, damit der Update-Part da nicht reinpfuschen kann. Das will ich aber möglichst umgehen! Alternative in aussicht?

    @ThuCommix
    Ja sry, dass ich soviel schreib xD
    Wenn du auf die KeyBoard-Events reagierst wird die Geschwindigkeit theoretisch stark schwanken können. Wenn du auf die Events reagierst und Boolean-Variablen wie "Key_Up/Down/Left/.." auf True oder False setzt jenachdem ob die Taste gedrückt ist, kannst du im Update-Part damit weiterarbeiten: Wenn Key_Up gedrückt, dann soll sich der Spieler in Blickrichtung nach oben bewegen. Du hast die vergangene Zeit seit dem letzen update, die gewünschte Gehgeschwindigkeit und kannst so die neue Position berechnen:

    'XNeu = XAlt + Geschwindigkeit * Zeit * math.Cos(winkel)
    'YNeu = YAlt + Geschwindigkeit * Zeit * Math.Sin(winkel)

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

    Bei meiner 2.5D Engine ist mir das sehr stark aufgefallen. Im Render-Part ist es nunmal so, dass zuerst die Wände und Böden berechnet und "gezeichnet" werden und erst dann die Sprites (also Figuren und Objekte wie Bäume). Wenn man nun mehr Updates als Draws macht, dann kann/wird es unter einer geringen Framerate vorkommen, dass bei einem Kameraschwenk die Objekte unter anderem Winkel dargestellt werden als Boden/Wände. Das wirkt dann so also ob die Sprites irgendwo "festkleben" würden und verzögert ihre richtige Position auf dem Bild einnehmen.
    Das passiert also nur, weil ein häufigeres Updaten dazu führt, dass sich die Positionen während dem zeichnen verändern - quasie mehrere verschiedene Situationen auf einem Bild dargestellt werden.

    Ist aber auch nur ein Effekt - wie die clipping und tastatur-bugs - der bei geringen Frameraten vorkommt. Unter dem Gesichtspunkt würde ich Grafikfehler eher hinnehmen können als einen Fehler in der Spielmechanik. Wer versucht bei weniger als 30FPS zu spielen muss dann eben mit rechnen...

    Der einzige brauchbare Lösungsansatz wäre wohl vor dem Zeichnen eine komplette Kopie aller Informationen anzulegen - so würde das Update da nichtmehr reinpfuschen können. Das failt imo aber hart und drückt die Performance vermutlich ein gutes Stück nach unten..

    Ich denke mal, dass in einem reinen 2D-Spiel diese Grafikfehler garnicht auffallen würden - also ist die 2-Thread-Variante die bessere. 2.5D ist da ja was anderes.
    Ich habe mir jetzt vorgenommen, das Mapsystem ein bischen zu optimieren ich habe da an soetwas gedacht:

    Events
    0;0|Message<Willkommen am Spawnpunkt>
    60;60|LoadMap</myhouse.map>
    ...
    End Events
    Region
    Size(100;0)|Location(0;0)|grastype1|grastype1|walkable
    Size(700;100)|Location(100;0)|water|water|walkable
    ...
    End Region


    Was haltet ihr davon? Die Mapdatei wird aufjedenfall kleiner, und lässt sich auch leichter erstellen, da man gleich große (gleiche) Flächen abdecken kann.
    Sieht aus eigene Auge besser lesbar aus, was aber eig. egal ist sobald man einmal einen funktionierenden Editor/Parser geschrieben hat.
    Wobei ich nicht glaube das man beim einlesen der Map auf performance o.ä. legen muss ;)
    (Außer wenn du wirklich nur eine große Map erstellen wilst, wo nur die Häuser und Höhlen etc. in eine extra Datei kommen)

    Edit: Ok, und es kommt natürlich auf die Anzahl der Layer in verbindung mit der Kartengröße an.
    Eine 50.000 x 50.000 Tile große Map mit 8 Layer, könnte schon heftig werden ^^
    (Fragt mich nicht wiso 8 Layer, hab ich aber schon von einigen gehört).