2D Map Editor / Tile Engine von ??? |
Hi Ich hab hier mal nen ganz simplen Map Editor gemacht. Ist wirklich nur sehr Simpel und die Map besteht nur aus Grafik Informationen, also keine Map mit mehreren Ebenen oder sowas. Die Map kann geladen werden oder neu erstellt. Mit den Cursortasten kann man die Map scrollen. Per Maus kann man die Tiles verändern (einfach draufklicken). Der Editor hat keinerlei Menu oder so und wird per Sourcecode konfiguriert ;) Was vielleicht das besondere daran ist: Viele Programmieren Maps mit Arrays, ich persönlich finde die Arrays einfach nicht so toll und manchmal verwirrend. Hab deswegen die Map mit nem Type programmiert. Hier ist ein link zum downloaden des Editors inkl. Testmap und Tiles. [url]http://www.zehr.de/bb/map_edit.zip[/url] Und hier trotzdem mal den Code: [code:1:130b43088b] ;--- Scroll Editor ------- by Jolinah ---- ;Dieser Editor benutzt die Auflösung 800x600 ;Die Tile grösse ist 40x40 ;Es sollte nichts an der Auflösung oder der Tile grösse geändert werden ;da ich diese nicht mit Variablen programmiert habe. ;Wem dieser Code weiterhilft und ihn benutzen will kann das mit der Auflösung und ;den Tiles natürlich ändern sofern er weiss was er macht. ;Noch was über meinen Programmierstil ;) ;Ich weiss das mein Code vielleicht nicht der schönste ist, und ich denke manches hätte ;ich vielleicht auch einfacher machen können. Aber jeder macht das irgendwie auf ;seine Art, hauptsache man versteht den Code selbst noch. ;Trotzdem habe ich versucht den Code ein bisschen mit Kommentaren zu versehen ;und ein bisschen zu Strukturieren, damit ihr den Faden nicht so schnell verliert :p ;(c) gibt es nicht :), Der Code kann frei verwendet, verändert usw. werden. ;Ich bin froh falls ich mit dem Code jemandem weiterhelfen konnte. ;Grafikmodus 800x600 und Doublebuffering aktivieren. Graphics 800,600,32,1 SetBuffer BackBuffer() ;Bilder Global iGras = LoadImage("gfxgamegrass.bmp") ;Tile 1 Global iStein = LoadImage("gfxgamestein.bmp") ;Tile 2 Global iStein2 = LoadImage("gfxgamestein2.bmp") ;Tile 3 Global iBack = LoadImage("gfxgameack.bmp") ;Tile 4 ;Types Type Tile ;Viele Arbeiten mit Arrays (Dim), ich hab diesmal Type vorgezogen. Field x,y Field image End Type Global map.Tile ;Variablen Global map_tiles_x = 40 ;Map besteht aus 40 Tiles in der X Achse. 2 Bildschirm, kann beliebig sein. Global map_tiles_y = 30 ;Map besteht aus 30 Tiles in der Y Achse. 2 Bildschirm, kann beliebig sein. Global scroll_x = 0 ;Scroll Startwerte für den Editor, am besten so lassen. Global scroll_y = 0 Global scroll_x_max = (map_tiles_x * 40 * -1) + 800 ;Berechnet anhand der Tiles wie viel gescrollt Global scroll_y_max = (map_tiles_y * 40 * -1) + 600 ;werden darf. Global mapname$ = "mapsmap1.map" ;Map die geöffnet wird. "" für neue Map erstellen. Global newmapname$ = "" ;Falls eine neue Map erstellt wird, hier den Dateinamen angeben. ;Die neue Map wird dann in dieser Datei gespeichert. ;Vorbereitungen... If mapname$ <> "" ;Falls eine Map angegeben wurde, lade sie. LoadMap(mapname$) Else ;Wenn nicht, erstelle eine neue in der Grösse wie oben definiert. NewMap() EndIf MoveMouse(400,300) ;Maus in die Mitte des Bildschirms bewegen. ;\ Haupt Programm Schleife \\\\\\\\\\\\\\\\\\\\ While Not KeyHit(1) Cls Gosub Drawtiles Gosub Eingabe Gosub Mouse Flip Wend If mapname$ <> "" ; Wenn eine Map geladen wurde... SaveMap(mapname$) ; Speicher die Map in der selben Datei. Else ; Wenn eine neue Map erstellt wurde... SaveMap(newmapname$) ; Speicher die Map in einer neuen Datei (welche oben angegeben wurde) EndIf SauberMachen() ; ;) Gibt den Speicher wieder frei. End ;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ;-- Unterprogramme ---------------------------------------------------------------------------------- ;- Zeichnet die Tiles -- .Drawtiles For map.Tile = Each Tile If mapimage > 0 And IsOnScreen(mapx,mapy) Select mapimage Case 1 DrawImage iGras, mapx + scroll_x, mapy + scroll_y Case 2 DrawImage iStein, mapx + scroll_x, mapy + scroll_y Case 3 DrawImage iStein2, mapx + scroll_x, mapy + scroll_y Case 4 DrawImage iBack, mapx + scroll_x, mapy + scroll_y Default End Select EndIf Next Return ;- Tastatureingabe und Scrollüberprüfung -- .Eingabe If KeyDown(205) scroll_x = scroll_x - 2 EndIf If KeyDown(203) scroll_x = scroll_x + 2 EndIf If KeyDown(208) scroll_y = scroll_y - 2 EndIf If KeyDown(200) scroll_y = scroll_y + 2 EndIf If scroll_x < scroll_x_max Then scroll_x = scroll_x_max If scroll_x > 0 Then scroll_x = 0 If scroll_y < scroll_y_max Then scroll_y = scroll_y_max If scroll_y > 0 Then scroll_y = 0 Return ;- Mauseingaben und Sachen zeichnen die mit der Maus zusammenhängen -- .Mouse For map.Tile = Each Tile If MouseX() - scroll_x > mapx And MouseX() - scroll_x < mapx + 40 And MouseY() - scroll_y > mapy And MouseY() - scroll_y < mapy + 40 Color 255,255,255 Rect mapx + scroll_x,mapy + scroll_y,40,40,0 If MouseHit(1) Then CycleTile(map.Tile) EndIf Next Color 255,0,0 Rect MouseX() -5,MouseY() - 5, 10, 10 Return ;-- Funktionen -------------------------------------------------------------------------------------- ;- LoadMap -- Lädt eine Map - Function LoadMap(datei$) file = ReadFile(datei$) If Not file Then Return map_tiles_x = ReadInt(file) map_tiles_y = ReadInt(file) scroll_x_max = (map_tiles_x * 40 * -1) + 800 scroll_y_max = (map_tiles_y * 40 * -1) + 600 For map.Tile = Each Tile Delete map.Tile Next For x = 1 To map_tiles_x For y = 1 To map_tiles_y map.Tile = New Tile mapx = (x * 40) - 40 mapy = (y * 40) - 40 mapimage = ReadInt(file) Next Next CloseFile(file) End Function ;- SaveMap -- Speichert eine Map - Function SaveMap(datei$) file = WriteFile(datei$) If Not file Then Return WriteInt file, map_tiles_x WriteInt file, map_tiles_y For map.Tile = Each Tile WriteInt file, mapimage Next CloseFile(file) End Function ;- NewMap -- Erstellt eine neue (leere) Map - Function NewMap() For x = 1 To map_tiles_x For y = 1 To map_tiles_y map.Tile = New Tile mapx = (x * 40) - 40 mapy = (y * 40) - 40 mapimage = 0 Next Next End Function ;- CycleTile -- Verändert das Tile (z.Bsp. wenn man mir der maus auf nem Tile klickt) - Function CycleTile(t.Tile) timage = timage + 1 If timage > 4 Then timage = 0 End Function ;- IsOnScreen -- Prüft ob ein Tile gezeichnet werden soll oder nicht - ; Tiles zu weit ausserhalb des Bildschirms sollen nicht gezeichnet werden - Function IsOnScreen(x,y) onscreen = True If x * -1 > scroll_x + 40 Then onscreen = False If x * -1 < scroll_x - 800 Then onscreen = False If y * -1 > scroll_y + 40 Then onscreen = False If y * -1 < scroll_y - 600 Then onscreen = False Return onscreen End Function ;- SauberMachen -- Gibt den Speicher wieder frei der bezogen wurde... - Function SauberMachen() FreeImage iGras FreeImage iStein FreeImage iStein2 FreeImage iBack For map.Tile = Each Tile Delete map.Tile Next End Function [/code:1:130b43088b] |
von ??? |
Hmmm es hat schon einen grund das viele Arrays nehmen: Das ist bei einer Tileengine schneller (ok, bei kleinen Maps ist es egal, aber wenn du Types nimmst wird das Programm bei riesigen Tilemaps sehr langsam da alle Tiles durchgegangen werden müssen. Bei Arrays kann man z.b. zum Zeichnen einfach nur die Tiles durchgehen die man sieht, so dass die Geschwindigkeit immer gleich ist) und viel einfacher. Außerdem kann man direkt auf ein Array zugreifen, was bei Types bei weitem nicht so einfach ist. Beispiel: Ändern eines Tile-Wertes bei Tile x|y zu z. (Die Tiles sind 32 Pixel groß) [code:1:ab6af97b4e] ;Array: map_array(x/32, y/32)=z ;Type: for h.tile = each tile if hx=x and hy=y then hvalue=z exit Endif Next [/code:1:ab6af97b4e] Bei nem Editor ist das noch nicht so dramatisch aber in einem Spiel sollte man das aus Geschwindigkeits und übersichtlichkeits Gründen doch lieber wie üblich mit den Arrays machen. |
von ??? |
Hm, ok danke. Dann werd ich wohl Arrays nehmen. Ich hatte da allerdings schon oft Probleme obwohl alle sagen das es einfacher ist als Types :). Ausserdem hab ich im obigen Beispiel auch nur die Tiles gezeichnit die Sichtbar sind ;). Was aber stimmt ist das alle Tiles mit der Schleife immer wieder abgefragt werden müssen... Vielleicht werd ich hier nochmal ein paar Fragen stellen falls ich mit den Arrays irgendwie an ein Problem stosse was ich zwar nicht hoffe :) Ach ja die erste Frage kommt schon :) Mit nem Type kann ich ja ziemlich einfach weitere Eigenschaften einbauen, wie zum Beispiel: [code:1:a876fa9312] Type Tile Field x,y ; im array ja nicht nötig Field image Field sprengbar ;ob ein block gesprengt werden kann.. Field begehbar ;ob das tile begehbar ist.. End Type [/code:1:a876fa9312] Wie würde man das mit nem Array realisieren? Natürlich könnte ich mit dem Begehbar auch 2 Map Ebenen machen, die eine ist begehbar, die andere nicht. Aber wenn ich dann noch viele Zusätzliche Infos möchte.... |
von ??? |
Mit einem Array machst du es genauso [code:1:159267c4c2] Type T_Tile field X field Y field Z ; --- usw End Type Dim Array.T_Tile(DimX,DimY) for X=1 to DimX step 1 for Y=1 to DimY step 1 Array.T_Tile(X,Y) = New T_Tile next next [/code:1:159267c4c2] |
von ??? |
Dann versteh ich aber nicht wieso es dann auf diese Weise schneller laufen soll... Jetzt hat man nicht nur 1 Instanz vom Type sondern für jedes Tile eine. Oder ist das Tempo rein davon abhängig ob man halt nur 1 Eintrag hat oder ob man mehrere Einträge hat die mit ner Schleife durchgegangen werden? |
von ??? |
Bingo. Das dauernde Durchlaufen verbraucht unheimlich viel Tempo. Für ein Array wird aber eine Liste von Pointern angelegt, so daß direkt auf die Speicherstelle zugegriffen werden kann. |
von ??? |
Achso, danke. Naja dann mach ich mich mal daran den Editor und das geplante Spiel umzuproggen oder neu zu proggen :) |
von ??? |
Hab das ganze nun umgeproggt und benutze ein Array. |