Page 2 of 4 FirstFirst 1234 LastLast
Results 11 to 20 of 34

Thread: I decided to start my RPG game in DelphiX and Im very happy

  1. #11

    I decided to start my RPG game in DelphiX and Im very happy

    Thanks Alimonster...

    I am not sure how I have the DXDraw component setup at the moment, but I am pretty sure there is some setting (boolean) relating to the VSync and so I will try this tonight.

    Also, about your bonus question... I would have to say on the near suicidal bordom stage to write that much But, I am glad you did as it has provided me a good understanding.

  2. #12

    Here is extract from my .DFM code

    [pascal]
    object DXDraw: TDXDraw
    Left = 0
    Top = 0
    Width = 320
    Height = 320
    AutoInitialize = False
    AutoSize = True
    Color = clBtnFace
    Display.BitCount = 24
    Display.FixedBitCount = True
    Display.FixedRatio = True
    Display.FixedSize = False
    Display.Height = 600
    Display.Width = 800
    Options = [doAllowReboot, doAllowPalette256, doCenter, doFlip, do3D, doDirectX7Mode, doRetainedMode, doHardware, doSelectDriver, doZBuffer]
    SurfaceHeight = 320
    SurfaceWidth = 320
    OnFinalize = DXDrawFinalize
    OnInitialize = DXDrawInitialize
    TabOrder = 0
    end
    [/pascal]

    BTW, I have a question, how can I save and load an array of any data to a stream without knowing the data only the name of the array :?:
    do not FEAR, I is here

  3. #13

    I decided to start my RPG game in DelphiX and Im very happy

    Thanks

    I have got mine running at a steady 80fps (on my machine) no matter what is displayed now. I also have another question...

    Because my tiles are somewhat smaller and were stretched in my original version of this game using a group of TImage components, I wanted to do the same thing on this. However when I use the StretchDraw() function, my framerate drops to about 2 or 3fps (from 80)... strange that. Anyone got any ideas? Or will I have to find new larger tilesets.

  4. #14

    Re: Here is extract from my .DFM code

    Quote Originally Posted by Karaman
    BTW, I have a question, how can I save and load an array of any data to a stream without knowing the data only the name of the array :?:
    You can use the WriteBuffer/ReadBuffer or Write/Read functions. However, you have to be careful when saving strings or dynamic arrays, and pointers are a little annoying too.

    For a standard array, SizeOf(Array_Thing) will give you the size in bytes; this lets you save the info directly:

    [pascal]procedure SaveMe(const Mem: TStream);
    var
    x: array[0..2] of Integer;
    begin
    // todo: init x somehow
    Mem.WriteBuffer(x[0], SizeOf(x));
    end;[/pascal]

    The above works fine for standard types that don't need memory allocation. You'd use ReadBuffer to read in the info again. However, if you're using dynamic memory then sizeof(x) will always give 4 (bytes), since the dynamic array is actually a pointer to memory behind the scenes. In that case, you'd have to save the length of the array first, then the array contents if necessary:

    [pascal]procedure Save(const str: TStream);
    var
    x: array of Integer; // dynamic array here
    Size: Integer;
    begin
    SetLength(x, 4); // allocate 4 elements

    // now the tricky part: we have to save the length first,
    // then calculate the size of the array in bytes

    Size := Length(x);

    // write the length
    str.WriteBuffer(x, SizeOf(x));

    if Size > 0 then
    str.WriteBuffer(x[0], Size * SizeOf(x[0]));
    end;

    procedure Load(const str: TStream);
    var
    x: array of Integer;
    Size: Integer;
    begin
    // get the length
    Mem.ReadBuffer(Size, SizeOf(Integer));

    SetLength(x, Size);

    if Size > 0 then
    Mem.ReadBuffer(x[0], Size * SizeOf(x[0]));
    end;[/pascal]

    Much the same idea for strings, too (not ShortStrings though, which are different). Save the length, then save the contents if necessary.

    You can't directly save arrays that store pointers to things; instead, you'd have to save the pointed-to memory and reconstruct the object when loading. Unfortunately, pointers aren't useful if they don't point to valid objects/memory. This rules out saving-in-one-line of code strings, dynamic arrays, and classes.

    Note that open arrays ("array of", but in a procedure (or function) parameter list) behave correctly with sizeof (I think!).
    "All paid jobs absorb and degrade the mind."
    <br />-- Aristotle

  5. #15

    Saving

    I am using MultiDimensional Arrays for GameData and I think It will not work correctly, but I will try

    100x a LOT
    do not FEAR, I is here

  6. #16

    I decided to start my RPG game in DelphiX and Im very happy

    If you're using a normal 2D multidimensional array (same width for each row), rather than a jagged one, then you could do this (note: really, really, untested - check it works!):

    [pascal][background=#FFFFFF][comment=#0000FF][normal=#000000]
    [number=#C00000][reserved=#000000][string=#00C000]type
    TTile = record
    x, y: Integer;
    PicIndex: Byte;
    Flags: Byte;
    end;
    PTile = ^TTile;

    T2DArray = array of array of TTile;

    procedure SaveMe(const arr: T2DArray; const Mem: TStream);
    var
    RowCount, ColCount: Integer;
    y, WidthOfRow: Integer;
    begin
    RowCount := Length(arr);
    if RowCount > 0 then
    ColCount := Length(arr[0])
    else
    ColCount := 0;

    // write out the array dimensions
    Mem.WriteBuffer(RowCount, SizeOf(RowCount));
    Mem.WriteBuffer(ColCount, SizeOf(ColCount));

    if (RowCount > 0) and (ColCount > 0) then
    begin
    WidthOfRow := ColCount * SizeOf(arr[0][0]);
    for y := Low(arr) to High(arr) do
    Mem.WriteBuffer(arr[y][0], WidthOfRow);
    end;
    end;

    procedure LoadMe(var arr: T2DArray; const Mem: TStream);
    var
    Rows, Cols: Integer;
    y: Integer;
    SizeOfRow: Integer;
    begin
    Mem.ReadBuffer(Rows, SizeOf(Rows));
    Mem.ReadBuffer(Cols, SizeOf(Cols));

    SetLength(arr, rows, cols);

    if (rows > 0) and (cols > 0) then
    begin
    SizeOfRow := Cols * SizeOf(arr[0][0]);

    for y := 0 to rows - 1 do
    begin
    Mem.ReadBuffer(arr[y][0], SizeOfRow);
    end;
    end;
    end;[/pascal]
    I think that the above will work, though I've not run it to find out. As always, it's not this simple if your game data contains classes, strings (but not shortstrings) or pointers to allocated memory. If it contains any of those, then you'll have to write functions to save the data instead of using a few calls to ReadBuffer/WriteBuffer.
    "All paid jobs absorb and degrade the mind."
    <br />-- Aristotle

  7. #17

    I decided to start my RPG game in DelphiX and Im very happy

    When I save/load an 2D array in my code I use something like:



    [pascal]
    TTile = record
    TileType: TTileType; //holds whether the player can walk on the tile etc
    TileIndex: Integer; // image
    end;

    TEvent = record
    Trigger: TEventTrigger; //What triggers the event, if the player steps on the tile or something else?
    Action: TEventAction; //What event will it be, change map, execute script?
    Param: String[10]; // For changing map and execute script files name etc.
    TileX, TileY: Integer; // which tile will have this event?
    PlayerPos: TPoint; // when changing map, where will the player start?
    end;

    TTransTile = record
    Xpos, Ypos: Integer; //Position
    TileImage: Integer; //Image
    end;

    TMapConfig = record
    MapWidth,
    MapHeight: Integer; //Map size
    TransTiles: Integer; //transparent tiles, for this I use a 1d array
    Events: Integer; //events, also 1d array
    Name: String[10];
    end;

    var
    MapConfig: TMapConfig;
    TileMap: array of array of TTile;
    TransTiles: array of TTransTile;
    Events: array of TEvent;

    procedure SaveMap(FileName: String);
    var
    Stream: TFileStream;
    X,Y,i: Integer;
    begin
    try
    Stream := TFileStream.Create(FileName, fmOpenReadWrite);
    except
    Stream := TFileStream.Create(FileName, fmCreate);
    end;

    try
    Stream.WriteBuffer(MapConfig, SizeOf(MapConfig));

    for y := 0 to MapConfig.MapHeight -1 do
    for x := 0 to MapConfig.MapWidth -1 do
    begin
    Stream.WriteBuffer(TileMap[x,y], SizeOf(TileMap[x,y]));
    end;

    for i := 0 to MapConfig.TransTiles -1 do
    begin
    Stream.WriteBuffer(TransTiles[i], SizeOf(TransTiles[i]));
    end;

    for i := 0 to MapConfig.Events -1 do
    begin
    Stream.WriteBuffer(Events[i], SizeOf(Events[i]));
    end;

    finally
    Stream.Free;
    end;
    end;

    procedure LoadMap(FileName: String);
    var
    Stream: TFileStream;
    X,Y,i: Integer;
    begin
    try
    Stream := TFileStream.Create(FileName, fmOpenRead);
    except
    ShowMessage('Error loading file.');
    Exit;
    end;

    try
    Stream.ReadBuffer(MapConfig, SizeOf(MapConfig));
    SetLength(TileMap, MapConfig.MapWidth, MapConfig.MapHeight);
    SetLength(TransTiles, MapConfig.TransTiles);
    SetLength(Events, MapConfig.Events);

    for y := 0 to MapConfig.MapHeight -1 do
    for x := 0 to MapConfig.MapWidth -1 do
    begin
    Stream.ReadBuffer(TileMap[x,y], SizeOf(TileMap[x,y]));
    end;

    for i := 0 to MapConfig.TransTiles -1 do
    begin
    Stream.ReadBuffer(TransTiles[i], SizeOf(TransTiles[i]));
    end;

    for i := 0 to MapConfig.Events -1 do
    begin
    Stream.ReadBuffer(Events[i], SizeOf(Events[i]));
    end;

    finally
    Stream.Free;
    end;
    end;
    [/pascal]

    I haven't loooked at Alimonster's code, it might be that his is much more efficient but this has worked for me so far at least.
    Signature:
    <br />This is a block of text that can be added to posts you make. There is a 255 character limit

  8. #18

    I decided to start my RPG game in DelphiX and Im very happy

    Quote Originally Posted by Ultra
    I haven't loooked at Alimonster's code, it might be that his is much more efficient but this has worked for me so far at least.
    It looks like your code does pretty the same thing, but with one problem. You mentioned the word "efficient," which has jogged my memory about what I missed in the previous post.

    I don't know how 2D dynamic arrays are stored in memory. If they're entirely consecutive (rather than each row being in a different area of memory), as with normal 2D arrays, then you only need one WriteBuffer/ReadBuffer for the entire map - sod all the loops .

    [pascal][background=#FFFFFF][comment=#0000FF][normal=#000000]
    [number=#C00000][reserved=#000000][string=#00C000]type
    TTile = record
    // stuff goes here
    end;

    T2DArray = array of array of TTile;

    procedure SaveMe(const arr: T2DArray; const mem: TStream);
    var
    SizeX, SizeY: Integer;
    begin
    SizeX := Length(arr);
    if SizeX > 0 then
    SizeY := Length(arr[0])
    else
    SizeY := 0;

    // write the map size
    mem.WriteBuffer(SizeX, SizeOf(SizeX));
    mem.WriteBuffer(SizeY, SizeOf(SizeY));

    // and the **entire map in one go **
    if (SizeX > 0) and (SizeY > 0) then
    mem.WriteBuffer(arr[0][0], SizeX * SizeY * SizeOf(arr[0][0]));
    end;[/pascal]

    ...and the same deal for loading .

    What's important here: the hard disc is bloody slow, as with all input devices (think about when your computer thrashes the hard disc getting virtual memory; that's much slower than using RAM). As a result, you want to do as few reads as you possibly can, reading in big chunks. This will minimize the slowness of the hard disc I/O. RAM is very quick - read in stuff to memory, and parse it *there* .

    Your code, Ultra, seems to be doing a read/write per tile (there will be a lot of 'em remember!). Think about this: each tile will be tightly packed together in the map, which means you can write many at the same time. If you write a tile[y,x], SizeOf(Tile[y,x]), then you're writing one tile. If you do the same, but 2 * SizeOf(Tile[y,x]), then you'll be writing two tiles at the same time (the expected one, plus the next one)! Remember that all your objects in the array, by definition, will be the same element type, and hence, the same size.

    My previous code snippet was done because I'm not sure if dynamic 2D arrays are sequential in memory. I'd guess they are, but without checking, I couldn't be certain. As a result, the least disc activity possible is to write out one row per outer loop. I'm absolutely sure that the rows of a 2D array will be stored sequential (anything else is unthinkable!). However, if my new assumption that the entire array will be contiguous holds, then no loops are necessary at all.

    If you're planning on doing lots of fiddling with a file then read as much of it into memory as you can each time, For example, you could use a TMemoryStream and TFileStream together - Create your filestream, use the memory one's CopyFrom, and use the *in memory* version. This will give big speed-ups (big, big ones!).
    "All paid jobs absorb and degrade the mind."
    <br />-- Aristotle

  9. #19

    Many, Many IMPROVEMENTS

    now my game has an official web page

    http://www.plovdivart.com/karaman/dnd/

    Updates:

    added support for

    1. Triggers
    2. Switches
    3. Containers
    4. Better Doors

    created encryption system (NOT enabled for convenience)
    do not FEAR, I is here

  10. #20

    I decided to start my RPG game in DelphiX and Im very happy

    Thanks for the tips Alimonster. I'm a bit to tired now and then I'll be gone for a couple of days, but then I will have a second look at my code based on your reply. If I get any troubles I know who to call.
    Signature:
    <br />This is a block of text that can be added to posts you make. There is a 255 character limit

Page 2 of 4 FirstFirst 1234 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
  •