Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi rpg-herumlaufkarten-speicherformat (https://www.delphipraxis.net/110420-rpg-herumlaufkarten-speicherformat.html)

dajuhsa 17. Mär 2008 23:11


rpg-herumlaufkarten-speicherformat
 
Hi,

ich arbeite an einem RPG mit rumlaufen und kämpfen, ganz im Pokemon-Stil.
Jetzt habe ich mir überlegt, die Karte, auf der man momentan rumläuft (aus einzelnen Feldern aufgebaut)
so zu laden:

Delphi-Quellcode:
type
TKarte = Array of Array of TFeld;
var
AktuelleKarte:TKarte;

...

procedure KarteEinlesen(var ZuAenderndeKarte:TKarte;const AKarte:TKarte);
var i,j:integer;
begin
  SetLength(ZuAenderndeKarte,Length(AKarte),Length(AKarte[0]));
  for i := 0 to High(AKarte) do
  for j := 0 to High(AKarte[0]) do
    ZuAenderndeKarte[i,j] := AKarte[i,j];
end;
Meine Frage ist jetzt:
wie soll ich die Karten-arrays speichern?
Ich suche irgendeine Datenbankfreie Lösung, um so eine Teilkarte in einer Datei zu speichern.

Ich hoffe, ihr versteht mein Problem :dp:

Flips 17. Mär 2008 23:14

Re: rpg-herumlaufkarten-speicherformat
 
Hi,

poste mal bitte die Deklaration von TFeld.

dajuhsa 18. Mär 2008 00:06

Re: rpg-herumlaufkarten-speicherformat
 
hab mir noch nix überlegt, es könnte ein integer sein, also:
0 für leeres feld mit gras
1 für leeres feld mir kies
2 für felswand
...

Flips 18. Mär 2008 13:19

Re: rpg-herumlaufkarten-speicherformat
 
Also wenn 255 verschiedene Eigenschaften reichen, dann würd ichs über chars (chr & ord) machen:
Delphi-Quellcode:
//Array
type TKarte = array of array of byte;


//Speichern
list := TStringlist.Create;
try
  list.BeginUpdate;
  for i := 0 to High(AKarte) do
    begin
      buf := '';
      for j := 0 to High(AKarte[i]) do
        buf := buf + chr(AKarte[i][j]);
      list.Add(buf);
    end;
  list.EndUpdate;
  list.SaveToFile('datei.txt');
finally
  FreeAndNil(list);
end;

//Laden
list := TStringlist.Create;
try
  list.LoadFromFile('datei.txt');
  SetLength(AKarte,list.Count-1);
  for i := 0 to High(AKarte) do
    begin
      SetLength(AKarte[i],length(list[i])-1);
      for j := 0 to High(AKarte[i]) do
        AKarte[i][j] := ord(list[i][j]);
    end;
finally
  FreeAndNil(list);
end;
Ungetestet!!

Bei größerem Bedarf an Eigenschaften:
Entweder du nutzt Hier im Forum suchenexplode und Hier im Forum suchenimplode oder (wie ich es mache) du nimmst für ein Spieldfeld von 64*64 einfach ein ebensogroßes Bitmap und ordnest jeder Farbe eine Eigenschaft zu. Dann hast du genug mögliche Eigenschaften und es lässt sich leicht auslesen und speichern!

dajuhsa 18. Mär 2008 20:04

Re: rpg-herumlaufkarten-speicherformat
 
ja, danke.
ich denke mal, ich hab es grob verstanden.
Danke dir, mfG
:wink:

Flips 18. Mär 2008 20:06

Re: rpg-herumlaufkarten-speicherformat
 
Hab jetzt anhand deiner Beitragszahl geschätzt, dass du Delphi schon soweit beherrscht :-)
Wenn du's nich verstehst / umsetzen kannst dann poste nur wieder hier rein^^

dajuhsa 18. Mär 2008 20:38

Re: rpg-herumlaufkarten-speicherformat
 
ja ich versteh's,
ich hab mir ja auch erst überlegt, ne textdatei zu nehmen, nur dachte ich, dass es was besseres gibt und dass es leicht zu manipulieren wäre, aber wenn ich das als ressource mit einbinde oder die datei mit ner anderen Endung tarne, haut das schon hin :mrgreen:

CodyConcrete 18. Mär 2008 22:03

Re: rpg-herumlaufkarten-speicherformat
 
Hey,
Soweit ich mich entsinnen kann, kann man doch auch selbst Dateien von einem bestimmten Typ erstellen

Delphi-Quellcode:
FeldDatei = File of TFeld
Jetzt kannst du angenehm alle Daten der Felder in die Datei speichern. Das Problem, dass jemand die Datei manipulieren könnte, fällt auch weg. Außerdem ist es ne sehr angenehme Sache, wenn TFeld aus mehreren Variablen verschiedenen Typs besteht.

Das ganze klappt auf jeden Fall wenn dein TFeld ein Record-Typ ist und alle Elemente finit sind, also keine dynamischen Arrays enthält. Wie es bei einer Klasse aussieht kann ich dir nicht sagen, aber du könntest dort einfach einen Record für alle Daten machen, der dann als Eigenschaft der Klasse alle Daten speichert die später auch in der Datei gespeichert werden soll. Dann kannst du ein FileTyp von diesem Record machen und wieder angenehm speichern.

Wenn du willst, kann ich dir ja mal ein Beispiel daszu schreiben

3_of_8 18. Mär 2008 22:19

Re: rpg-herumlaufkarten-speicherformat
 
Der klassische Weg dafür:

Ein array of array of Byte, das man aus ner binären. Dazu gehört außerdem ein "Tileset", das ist ein Bild mit 16*16=256 Tiles. (ein Tile ist jeweils die kleinste Fläche auf einer Karte)

Das ist das Ground-Layer, also der Boden. Dazu gehört nochmal ein array[Byte] of Boolean, das darstellt, ob man über ein bestimmtes Tile gehen kann oder nicht.

Über den Ground-Layer kommt nochmal ein gleich aufgebautes Layer, das dann Objekte wie Häuser, Zäune usw. enthält.

Eine Karte besteht also aus Breite, Höhe, Tilesets für beide Layer, jeweils mit Kollisions-Map und zwei Maps für die Layer.

dajuhsa 18. Mär 2008 23:32

Re: rpg-herumlaufkarten-speicherformat
 
:shock: das wird ja immer komplizierter!
nicht, dass ich es nicht verstehen würde, aber das alles in source sinnvoll umzusetzen könnte schwierig werden.
außerdem muss ich mir ja vorher noch einen map-editor programmieren um die maps zu speichern :pale: ...

3_of_8 19. Mär 2008 07:44

Re: rpg-herumlaufkarten-speicherformat
 
Das wird nicht sonderlich kompliziert umzusetzen.

Pseudocode:
Delphi-Quellcode:
for I:=0 to Width-1 do
  for J:=0 to Height-1 do
  begin
    Draw(I*TILEWIDTH, J*TILEHEIGHT, TileSets[GroundLayer.TileSet][GroundLayer.Map[I, J]);
    Draw(I*TILEWIDTH, J*TILEHEIGHT, TileSets[UpperLayer.TileSet][UpperLayer.Map[I, J]);
  end;
Bei der Kollision lädst du einfach und schaust, ob die Spielfigur sich gerade ganz oder teilweise auf einem nicht-begehbaren Feld des Ground- oder Upperlayer befindet.

So in der Art wird es auch im Original-Pokemon-Spiel gemacht und auch z.B. im RPG-Maker.

dajuhsa 20. Mär 2008 19:15

Re: rpg-herumlaufkarten-speicherformat
 
ja stimmt eigentlich^^ danke für eure Hilfe, ich werde mich im (sehr warscheinlichen) Falle einen weiteres Problems einfach an euch wenden :dp:

dajuhsa 22. Mär 2008 21:39

Re: rpg-herumlaufkarten-speicherformat
 
hi nochmal :mrgreen: also ich dachte ich versteh es, hab mich an die arbeit zu nem level-editor gemacht und bin stecken geblieben.
Soll ich jetzt also 3 Karten machen: die Bodentexturen, die Objekte und die Kollisionen? Undwie soll ich die dann speichern? alle in den gleichen Textfile oder was :gruebel: ich komm echt nicht weiter, außerdem hat mich das code-beispiel
Delphi-Quellcode:
for I:=0 to Width-1 do
  for J:=0 to Height-1 do
  begin
    Draw(I*TILEWIDTH, J*TILEHEIGHT, TileSets[GroundLayer.TileSet][GroundLayer.Map[I, J]);
    Draw(I*TILEWIDTH, J*TILEHEIGHT, TileSets[UpperLayer.TileSet][UpperLayer.Map[I, J]);
    //                                                  ^^^^^^^             ^^^^^^^^^
  end;
schon etwas verwirrt, was ist denn da jetzt TileSet und Map und die verschachtelten [ und ] verwirren etwas :stupid:

es besteht wohl noch etwas erklärungsbedarf für mich ^^"
bitte Hilfe

TGLDX 22. Mär 2008 22:08

Re: rpg-herumlaufkarten-speicherformat
 
Zitat:

Soll ich jetzt also 3 Karten machen: die Bodentexturen, die Objekte und die Kollisionen? Undwie soll ich die dann speichern? alle in den gleichen Textfile oder was ich komm echt nicht weiter, außerdem hat mich das code-beispiel
Hier mal ein Beispiel:
Delphi-Quellcode:
type
  tTile = Integer;
  tLayer = array of array of tTile;
  tMap = array[0..2] of tLayer;
Also ein Tile ist ein Feld deiner 2d-Karte. Die Karte hat 3 (oder mehr) "Layer", jedes davon ist so groß wie die Karte und stellt quasi eine "Scheibe" von ihr dar. Die einzelnen Tiles können verschiedene Informationen beinhalten. Die Tiles in Layer 0 könnten Beispielsweise den Index des zu verwenden Bildes darstellen. Die Tiles aus Layer 1 wären zum Beispiel Objekte die transparent darüber gezeichnet werden.
Das 3. Layer könnte Informationen über Passierbarkeit beinhalten (z.b 0 passierbar,1 unpassierbar, 2 nur passierbar wenn die Spielfigur fliegt). Ein anderer Ansatz wäre dabei, dass da 3. Layer Infos enthält wie z.B. 0 normales Feld,54 Figur nimmt Schaden wenn sie darüber geht, 100 unpassierbares normales Feld (Der Unterschied besteht darin, dass beim 1. Ansatz die Passierbarkeit direkt gespeichert wird,beim 2. wären zum Beispiel Felder mit Wert < 100 passierbar, mit Wert >= 100 unpassierbar).

Speichern ist im Prinzip nicht schwer, hier mal ein möglicher Aufbau der Datei:
Breite der Karte in Tiles
Höhe der Karte in Tiles
Anzahl der Layer (falls variabel)
1. Tiles des 1. Layers
...
Letztes Tile des 1. Layers
...

mfg TGLDX

dajuhsa 22. Mär 2008 22:25

Re: rpg-herumlaufkarten-speicherformat
 
also ein file of integer, oder was?

Namenloser 22. Mär 2008 23:42

Re: rpg-herumlaufkarten-speicherformat
 
Tipp von mir: Lass das lieber mit dem "file of ...". Das ist aus der Steinzeit und auch der "klassische" Weg, aber meiner Meinung nach wirklich nicht zu empfehlen, weil es unflexibel und kompliziert ist. Guck dir lieber mal Streams an, damit kann man meiner Meinung nach sehr viel besser arbeiten.

Hier mal eine Erklärung über die Grundstruktur der unten deklarierten typen: tMap enthält zwei Layer vom Typ tTileset. dieses tTileSet ist ein zweidimensionales Array von dem record-typ tTile. tTile wiederum enthält alle Infos zu einem Tile, in diesem Fall nur den Typ, und ob man damit kollidiert. Das kann natürlich noch erweitert werden, z.b. könntest du Portale bauen, bei denen du dann speicherst, an welcher Stelle der Spieler rauskommt, oder ein Flag für wasser etc...

Pseudocode:
Delphi-Quellcode:
type
  tTileType = (tFloor,tGrass,tTree);
  tTile = record // Natürlich könnte man sich den Record auch sparen, und stattdessen tTileType benutzen, wo man dann
                 // allerdings anhand des Typen erkennen müsste, ob es eine Kollision gibt. Ich würde hier auf jeden Fall
                 // einen Record nehmen, denn wer weiß, was du später noch an Zusatzinformationen speichern willst
    Type: tTileType;
    Collide: Boolean;
  end;
  tTileset = array of array of tTile; // Beachte, dass der erste Index hier Y und der zweite X. Vom Gefühl her würde man es
                                      // vielleicht anderherum machen, aber die Erfahrung hat mich gelehrt, dass es sorum auf
                                      // Dauer praktischer ist
  tMap = array[0..1] of tTileset; // 0 = bottomlayer, 1= toplayer
var
  MemStream: tMemoryStream;
  Map: tMap;
  TileSetW,TileSetH: integer; // Breite und Höhe des Tilesets
  i,y,x: integer;
begin
  // Höhe und Breite des Tilesets in lokalen Variablen zwischenspeichern
  TileSetH := high(Map[0]) + 1;
  TileSetW := high(Map[0][0]) + 1; // Normalerweise sollte man hier noch prüfen, ob es die Höhe des Tilesets >0 ist, weil es
                                   // hier sonst eine Zugriffverletzung geben könnte
  memstream := tmemorystream.create;
  // Aus Performancegründen wird jetzt der gesamte Speicherbedarf ausgerechnet:
  // Zwei Integers (Höhe und Breite) + Anzahl der Tiles * Platzbedarf eines Tiles, und das ganze für jeden der zwei layer
  memstream.size := SizeOf(integer)*2+TileSetH*TileSetW*sizeof(tTile)*2;
  memstream.position := 0; // Wir fangen bei 0 an zu schreiben
  // Für jeden Layer:
  for i := 0 to 1 do
    for y := 0 to TilesetH-1 do
      for x := 0 to TilesetW-1 do
        memstream.write(Map[i][y][x],sizeof(tTile)); // Das hier ist der eigentliche Teil^^
  // Inhalt des memoryStreams auf der festplatte ablegen
  memstream.savetofile('fertig.map');

  memstream.free;
end;
Okay, sieht jetzt vielleicht doch etwas kompliziert aus, aber das meiste davon sind ja auch Kommentare und Typendeklarationen :mrgreen:
So, jetzt ist meine Antwort c.a. drei fünf mal so lang ausgefallen, wie ich erwartet hatte, ich hoffe, man versteht es wenigstens :oops:

dajuhsa 24. Mär 2008 12:24

Re: rpg-herumlaufkarten-speicherformat
 
naja, ich weiß zwar nicht was ein Stream für einen Vorteil hat, aber das erscheint mir einleuchtend. Ich hab mich auch noch nicht wirklich mit Streams befasst :oops: aber ich denke mal, das wird nicht allzu schwierig.

Zu deinem Code:

- Erstmal gefällt er mir :wink:

- erst Y dann X, das erscheint mir einleuchtend, da man es bei einem Textfile genauso macht, also erst der Zeilenindex und dann die Zeichennummer.

- die idee, das collide mit in das Tile zu nehmen erescheint mir zwar praktisch, allerdings hätte ich dann diese information zweimal, also im TopLayer und im GroundLayer, aber 14(Breite)*10(Höhe) = 140 Bits, also 18 Bytes pro Map sind ja nicht die Welt und allzu Komplex (Wasser, Portale, etc.) wird das ganze nicht werden, also kann ich das auch aus dem TopLayer ablesen(Objekt = nicht gehen können, kein Objekt = gehen können)

Delphi-Quellcode:
  memstream.write(TileSetH,4); //<-- gehört das nicht dazu? oder kann man das später irgendwie anhand der
  memstream.write(TileSetW,4); //streamgröße rausfinden? nicht, dass später die Zeilen zu früh/spät "abgehackt" werden
  for i := 0 to 1 do
    for y := 0 to TilesetH-1 do
      for x := 0 to TilesetW-1 do
        memstream.write(Map[i][y][x],sizeof(tTile));
- warum schreibt die ganze Welt eigentlich
Delphi-Quellcode:
x := sizeOf(Integer);
wenn man doch auch einfach
Delphi-Quellcode:
x := 4;
schreiben könnte oder irre ich mich da etwa? :mrgreen:

phXql 24. Mär 2008 13:22

Re: rpg-herumlaufkarten-speicherformat
 
Keine Magic numbers verwenden. 4 ist in dem Fall so eine :)

Namenloser 24. Mär 2008 18:29

Re: rpg-herumlaufkarten-speicherformat
 
Du weißt nie, wie groß ein Integer mal in zukünftigen/älteren Versionen sein wird/war.

dajuhsa 24. Mär 2008 21:15

Re: rpg-herumlaufkarten-speicherformat
 
ok ok... ich werds mir merken, aber was ist denn jetzt mit
Delphi-Quellcode:
mem.write(tilesetH,sizeof(integer));
mem.write(tilesetW,sizeof(integer));
ist das jetzt notwendig oder nicht?

Fussball-Robby 24. Mär 2008 21:29

Re: rpg-herumlaufkarten-speicherformat
 
Zitat:

Zitat von dajuhsa
- erst Y dann X, das erscheint mir einleuchtend, da man es bei einem Textfile genauso macht, also erst der Zeilenindex und dann die Zeichennummer.

Also mir erscheint das nicht einleuchtend. In einer Textdatei wird zuerst die Zeile angegeben, damit man sich grob orientieren kann, da Zeilen immer die gleiche Höhe, nicht aber immer die gleiche Länge haben.
Aber in der Mathematik, der Physik und überall wird IMMER zuerst die X-Koordinate angegeben. Oder hast du einmal eine Funktion von Delphi oder eine mathematische Gleichung gesehen, in der Y zuerst steht?
Deshalb: Nimm lieber X zuerst, dann kommst du nachher nicht durcheinander, weil du bei allen anderen Sachen X zuerst nehmen musst. :wink:

Mfg

dajuhsa 24. Mär 2008 21:45

Re: rpg-herumlaufkarten-speicherformat
 
@robby: das weiß ich doch, aber bei textdateien ist es halt so, aber hier ist das eigentlich sehr egal.

Fussball-Robby 24. Mär 2008 21:48

Re: rpg-herumlaufkarten-speicherformat
 
Naja, sehe ich nciht so, aber ist ja deine Entscheidung :?

dajuhsa 24. Mär 2008 21:59

Re: rpg-herumlaufkarten-speicherformat
 
nicht, dass ich mir nichts sagen ließe und ich nehme normalerweise auch zuert X, aber auch nur weil ich es gewohnt bin, keine ahnung was das bringen soll, höchstens, dass es die standart reihenfolge ist:
Delphi-Quellcode:
blub: array of array of TMöööp;
//      X       Y
//      1.      2.
ich werde in meinem programm mal prüfen, ob das einen unterschied macht :roll:

Namenloser 24. Mär 2008 22:34

Re: rpg-herumlaufkarten-speicherformat
 
Zur Info: TBitmap.Scanline speichert auch zuerst die Y Koordinate. Das war bei mir übrigens einer der Gründe, weshalb ich micht für [y,x] entschieden haben: ich musste nämlich teilweise Daten aus Bitmaps übernehmen - es ging nämlich um Kollisionsmasken. Hier wäre das vielleicht nicht unbedingt nötig, aber es tut doch keinem weh oder ;)

Fussball-Robby 24. Mär 2008 22:38

Re: rpg-herumlaufkarten-speicherformat
 
Zitat:

Zitat von NamenLozer
Hier wäre das vielleicht nicht unbedingt nötig, aber es tut doch keinem weh oder ;)

Nein, eigentlich nicht, es sei denn jemand stößt sich seinen Zeh am Y :mrgreen:
Ich sage ja auch nicht, dass es von Bedeutung für das Programm wäre, ich meinte nur, man solle lieber die mathematischen Grundsätze beachten und die X-Koordinate zuerst nennen. Mir ist das ja auch völlig egal, wie er es letztendlich macht, ich wollte ihm ja nur einen guten Rat geben :wink:

Mfg

dajuhsa 24. Mär 2008 23:01

Re: rpg-herumlaufkarten-speicherformat
 
was ich außerdem fragen wollte, ist, wie ich das TopLayer handhaben soll.
Soll ich mir 20x20er Bitmaps erstellen(meine Tilegröße)(so ist mein BottomLayer aufgebaut) wie z.B.
1.vertikaler zaunabschnitt
2.horizontaler "
3.Baumwurzeln
4.Baumstamm
5.Baumkrone linke Seite
6. " Mitte
7. " rechte Seite
8.Hauswand
9.Haustür
10.Dachteil 1
usw.
oder hat da jemand ne bessere Idee?

Namenloser 24. Mär 2008 23:22

Re: rpg-herumlaufkarten-speicherformat
 
Eine andere Möglichkeit wird es wohl kaum geben. RPGMaker macht es imho auch so, wobei ich das Programm nicht besitze.

Nur n00bs benutzen Images als Paintbox

dazar_t 24. Mär 2008 23:26

Re: rpg-herumlaufkarten-speicherformat
 
nja was heisst bessere, diese Idee ist doch "wunderbar" und einfach um zusetzen

dajuhsa 25. Mär 2008 00:08

Re: rpg-herumlaufkarten-speicherformat
 
Liste der Anhänge anzeigen (Anzahl: 1)
blösd daran finde ich nur, dass ich dann 10 verschiedene Bitmaps für ein Haus brauche :mrgreen: aber is schon ok^^
ICh freue mich echt, dass so viele hier antworten, ich hab mal meinen map-editor grob angefangen(hatte nicht viel Zeit diese Woche,sry) und häng ihn mal an:

Beschreibung
Man kann den Ground Layer bearbeiten,mit erstmal 20 verschiedenen Bodenexturen, die Maps sind immer 14(X-Koordinate :mrgreen: ) mal 10 Tiles groß, speichern geht noch nicht.

Quelltext gebe ich auch her, wenn es sein muss.

Namenloser 25. Mär 2008 00:21

Re: rpg-herumlaufkarten-speicherformat
 
Da scheinen einige texturen zu fehlen. Außerdem wäre es net, wenn du das nächste mal die Ordnerstruktur mitkopierst, damit man nicht erst anhand der Fehlermeldung eine entsprechende erstellen muss.

dajuhsa 25. Mär 2008 00:28

Re: rpg-herumlaufkarten-speicherformat
 
OMFG! ich wusste doch, ich hatte was vergessen

dajuhsa 25. Mär 2008 20:58

Re: rpg-herumlaufkarten-speicherformat
 
okay, habe es korrigiert, aber welche texturen fehlen deiner meinung nach? es sind 8 böden und 12 wände und die sind alle mit dabei und funktionieren

Namenloser 25. Mär 2008 21:25

Re: rpg-herumlaufkarten-speicherformat
 
Meiner Meinung nach fehlt da gar nichts, das hat dein Programm gesagt. Jetzt scheint aber alles nötige drin zu sein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:07 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz