Page 1 of 3 123 LastLast
Results 1 to 10 of 24

Thread: Formats

  1. #1

    Formats

    Well, another issue i've been having I realize i may be able to get help or at least a better understanding at these wonderfull forums.

    Currently, in my RPG map editor, i save maps by:

    1st) Load all data in a string

    In the string i load data in a fashion like:
    MapName|MapInfo|MapInfo|MapInfo then a line break. After that i scroll through all the tiles and save each tile data like: TileX,TileY,MoreData,...| Until its done. So my string roughly looks like:

    MapName|MapInfo|MapInfo|MapInfo
    TileX,TileY,MoreData,...|TileX,TileY,MoreData,...| TileX,TileY,MoreData,...|

    2nd) And then i simply save it to a file.

    This way when i go to open the file. I split the string by that line break, and then split the first half by the | character and now i have all that data. Then i go through the second half extracting all the tile information and loading it into my type.

    My question is... Is there any easier, maybe more professional way of going about this?
    I have a 2005 CRF 250 so <^>(>&lt<^>
    <br />http://www.gtrpg.com/

  2. #2

    Formats

    You should use a binary format instead i.e. use file streams, create a record for your file header and then use FileStream.Write to save everything to a file.
    There are some cases in which an ASCII-format may be helpful, e.g. if you want to be able to edit the files by hand. But in general, binary will be faster and easier to use.
    Ask me about the xcess game development kit

  3. #3

    Formats

    Example on doing this please? Is there a way to save a record?
    I have a 2005 CRF 250 so &lt;^&gt;(&gt;&lt&lt;^&gt;
    <br />http://www.gtrpg.com/

  4. #4

    Formats

    [pascal]
    type
    TMyRecord = record
    X, Y: Integer;
    B: Boolean;
    end;

    var
    FileStream: TFileStream;
    MyRecord: TMyRecord;
    begin
    MyRecord.X := 100;
    MyRecord.Y := 150;

    FileStream := TFileStream.Create('C:\MyFile.dat', fmCreate);
    FileStream.Write(MyRecord, SizeOf(MyRecord));
    FileStream.Free;
    end;
    [/pascal]

    Please also check the Delphi help file. Most objects/components are really well documented there.
    Ask me about the xcess game development kit

  5. #5

    Formats

    Just a small side note; when saving records this way, it's a good idea to use a packed record instead of a regular record, since a packed record always has the same size, so the data is less likely to get currupt when loading/saving.

    [pascal]
    type
    TMyRecord=packed record;
    [/pascal]
    BK - we.create (tm)

  6. #6

    Formats

    Ok well i set up everything to save like that. Now, i get access errors when I try and load. Here's what i'm doing to load:

    [pascal]Var TheMap : GTRPG_MAP_VER1;
    FileStream : TFileStream;
    I, X : Integer;
    begin
    //- New Load -
    Try
    FileStream := TFileStream.Create(FileName, fmOpenRead);
    FileStream.Read(TheMap, SizeOf(TheMap));
    FileStream.Free;
    ms_Name.Caption := TheMap.NAME;[/pascal]
    I have a 2005 CRF 250 so &lt;^&gt;(&gt;&lt&lt;^&gt;
    <br />http://www.gtrpg.com/

  7. #7

    Formats

    what is GTRPG_MAP_VER1? Please post it here.
    Ask me about the xcess game development kit

  8. #8

    Formats

    Ok these all inter-twine with eachother:

    [pascal]type
    GTRPG_MAP_NPC_VER1 = record
    NAME : STRING;
    SPRITE : STRING;
    MOVES : BOOLEAN;
    ATTACKS : BOOLEAN;
    ATTACK_MODE : INTEGER;
    ATTACKABLE : BOOLEAN;
    HP : INTEGER;
    MP : INTEGER;
    SPD : INTEGER;
    STR : INTEGER;
    ATTACK_1_TYPE : INTEGER;
    ATTACK_1 : INTEGER;
    ATTACK_2_TYPE : INTEGER;
    ATTACK_2 : INTEGER;
    VIEW_DISTANCE : INTEGER;
    WORK_TOGETHER : BOOLEAN;
    ROAMS : BOOLEAN;
    BEHAVIOR : INTEGER; // 1 Coward - 2 Normal - 3 Heroic
    PATH : STRING; // 1 UP - 2 RIGHT - 3 DOWN - 4 LEFT
    DROPS : STRING; // Item_ID Item_ID..
    end;


    GTRPG_MAP_BORDER_VER1 = record
    BORDER_UP : STRING;
    BORDER_DN : STRING;
    BORDER_LF : STRING;
    BORDER_RT : STRING;
    end;

    GTRPG_MAP_TILE_ANIMATION_VER1 = record
    ACTIVE : BOOLEAN; // Animation Active?
    TILES : TSTRINGLIST; // Tiles in animation
    INDEX : INTEGER; // Current Tile Displayed
    end;

    GTRPG_MAP_TILE_VER1 = record
    GROUND : Integer;
    MASK : Integer;
    ANIMATION : GTRPG_MAP_TILE_ANIMATION_VER1;
    MASK2 : Integer;
    ABOVE : Integer;
    ABOVE2 : Integer;
    ATTRIBUTE : Integer;
    ATTRIBUTE_PROPERTIES: String;
    end;

    GTRPG_MAP_VER1 = packed record
    NAME : STRING;
    ZONE : STRING;
    MUSIC : STRING;
    SKILL : STRING;
    BORDER_LOCATIONS : GTRPG_MAP_BORDER_VER1;
    MAP_NPCS : ARRAY OF GTRPG_MAP_NPC_VER1;
    MAP_TILES : ARRAY[0..15, 0..11] of GTRPG_MAP_TILE_VER1;
    end;[/pascal]
    I have a 2005 CRF 250 so &lt;^&gt;(&gt;&lt&lt;^&gt;
    <br />http://www.gtrpg.com/

  9. #9

    Formats

    The problem is that your records contain strings which are variable-length

    Example:
    'Hello World' = 11 Bytes
    'DGDev kicks a**' = 15 Bytes

    writing them to a file is no problem, but when you write them, you will only write the strings themselves and no information on how long they are (whereas with Integers for example, you always know that they're 32 bytes long).

    The solution is to use fixed length strings which you declarare like this


    [pascal]
    TMyRecord = record
    Blah: array[0..255] of Char;
    end;
    [/pascal]

    These are called null-terminated strings. You can work with them just like you would with a normal string but you have to restrict yourself to whatever length you chose.
    Ask me about the xcess game development kit

  10. #10

    Formats

    [pascal]GTRPG_MAP_TILE_ANIMATION_VER1 = record
    ACTIVE : BOOLEAN; // Animation Active?
    TILES : TSTRINGLIST; // Tiles in animation
    INDEX : INTEGER; // Current Tile Displayed
    end; [/pascal]

    I just saw this bit of code and this will also cause you some problems. String lists just like strings themselve have a variable length depending on how many entries they have. To store this record in a stream I suggest you do something like this:

    [pascal]GTRPG_MAP_TILE_ANIMATION_VER1 = record
    ACTIVE : BOOLEAN; // Animation Active?
    INDEX : INTEGER; // Current Tile Displayed
    TILELISTSIZE: INTEGER; // <--- New stuff
    TILELISTOFFSET: INT64; // <--- New stuff
    end; [/pascal]

    Note that this won't save the string list yet. The idea is that instead of storing the tile list itself in the record, you only store the size of the tile list and the offest (which is the position of the the list in your file).

    So you'd have to find out how big all your records are (if you convert all your strings to null-terminated ones you can use the SizeOf function to get the size).
    The next thing you have to do is find out how big your tile lists are. The SizeOf operator won't work for that (it will only return the size of the pointer which is always 4 bytes). Here's a very dirty solution for that problem:

    [pascal]
    var
    MyStringList: TStringList;
    MyMemoryStream: TMemoryStream;
    begin
    MyStringList := TStringList.Create;
    FillThis(MyStringList); // Just some bogus procedure that fills the string list
    MyMemoryStream := TMemoryStream.Create;
    MyMemoryStream.Clear;
    MyMemoryStream.Seek(0, soFromBeginning);
    MyStringList.SaveToStream(MyMemoryStream);
    end;
    [/pascal]

    To obtain the size of the memory stream, use the size property of the memory stream (MyMemoryStream.Size).

    With the size of the records you can calculate an offset and store it in the GTRPG_MAP_TILE_ANIMATION_VER1 record.
    After you have written all records to your file, you can then write the stringlists to it one after the other.


    This sounds like a lot of work and as matter of fact it is
    Unless you completely re-structure your records, I don't see how you could do it differently though.

    Another solution of saving structures of arbitrary length to a stream which involves some "abuse" is to turn all your records into TComponents and to then use the SaveComponentRes method of TFileStream... it works really well and will save you some trouble.
    Note that only published properties will be saved to the stream...
    If you need to store lists of records try using TCollections instead.
    It works but of course it's a hack...[/b]
    Ask me about the xcess game development kit

Page 1 of 3 123 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •