Results 1 to 10 of 121

Thread: G.T.A.2 Map Editor

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Any ideas how implement undo redo guys?
    I have tried several Delphi units for undo/redo, even with command patters and state machines. Even dig out some website archives for SHAREWARE (!) Delphi units for creating undo / redo and mailed to authors of them to get the units for free (without much hope for any response).
    Etc.

    I got them but nothing works for me. I see "lots" of examples that use simple TBitmap.SaveToStream method.
    Its neat and easy way to make undo / redo.

    But how about 3D map editor like this?
    Map is 256x256x8 (W*H*Z), i only draw small portion of it (20x20).

    I guess i have to invent "gamemap.portion.savetostream" command.

    Whole uncompressed map takes 6MB of disk space, depending how complex map is. But 6MB is minimum for empty map.
    So saving whole map each time is not way to go. it would work for small tilemaps / tilemap editors, but not in this case.

    One way would be just save all the blocks in current view but if camera moves, then what to do?
    I tried that without moving cam, it seems to work, its buggy a bit, i just cant think clearly atm why its buggy, i have to eat and come back to this.

    When camera moves i guess i have to remember the offset to the place where previous undo / redo was made or something and undo / redo in that area, or make some record and in record make a member called XYZpos for storing the start position of the area where the changes were made, dunno something like that maybe.

    Map has so easy format, i didnt know that making a undo/redo will be so difficult for this.
    I have read that if you dont think about undo/redo at the first time you create your app, integrating later any of the algorithms for undo/redo will be difficult.

    So i guess here i am.

    I could modify my rendering function if i could reorganize my map array somehow.

    This is where i need your help / tips / tricks / ideas how to do it.
    Even some pseudo code would help i guess.

    Thanks.
    Last edited by hwnd; 02-08-2013 at 03:57 PM.

  2. #2
    Few ways come to mind. All solutions consist primarily of array or list of undo operations. But what each operation is, may differ:
    1) Compress the map using TCompressionStream and TDecompressionStream. Your data size per undo-operation might go down to some number measured in kilobytes.

    2) Just save the action what was done, not whole map (unless necessary). You can make base-class TUndoAction, and inherit from it like:
    Code:
    // Some action where you select rectangular area, and move it in some direction...
    TMoveUndoAction = class(TUndoAction)
    public
      selEnd, selSize, moveDelta: TVector3f;
      procedure Execute; override;
    end;
    
    // Free tile-painting for map. You might need to save the entire map for this, so you can use the TCompressionStream
    // to write in TMemoryStream.
    TPaintUndoAction = class(TUndoAction)
    public
      map: TMemoryStream;
      procedure Execute; override;
    end;
    You get the idea, there can be lots of kinds of undo operations, some of which may not be related to tiles at all. And i'm not sure what all your editor can do.

  3. #3
    Ohh, you gave me great idea about compressionstream.. Thanks.
    I did a quick test atm, official large map fully compressed is 1.23MB.
    It contains lots of cubes / tiles. After 7z: 343KB

    Empty map, compressed 273KB.
    And now compressed with 7z: 385 bytes lol.

    This map format contains lots of 0. Thats why 7z is able to compress it so well.
    I will try with compressionstreams..

    Yes maps must be first compressed with specific way, before game is able to load them.
    For undo its not needed.

    This of course probably will be the easiest solution. Just take whole map and compress.
    And if i limit undo count, maybe it will even work.

    Atm i would like just to have undo / redo for tile "painting".

  4. #4
    Making Undo/Redo function laregly depends on how you want to track theese changes.
    If you are tracking changes for each cube seperately then I would suggest creating dynamical array of special records which will contain cube position, old and new state of it.
    If you are tracking changes of several cubes at once (making cube shaped hole in your terrain) then I you can euther use similar system as above with the only difference that you now have seperate arrays for each undo/redo action. Or you can create some kind of submaps (array smaller than the whole map array) which will store previus state of the map section before it was changed.

  5. #5
    Yeah, for each individual tile making undo / redo seems easy, but if user makes lots of changes, then he must wait alot before undo reaches the stage where he started to draw these tiles.
    I tried and its very slow.

    Its better to create group of undos.
    And i have found idea to create stack_of_[tile+tile_coord]_lists

    In c++ something like this: stack< list<unsigned long> > undolist;
    Actually instead if unsigned long there was a simple struct (record) which just contains tile_id and its XYZ coordinate.
    This way each modification is actually a group. Pop a list from stack, loop through each of its item, get XYZ and tile ID. Put these tile_ids back at these XYZ coords on map. And do this for each LIST item in stack.

    Atm im trying to implement this system. Undo first.
    Dunno how to do this in Delphi without generics but i will try this in a DLL again.
    I already can successfully receive and send block_data to / from C++ DLL.

  6. #6
    You could save a new undo-point of the map when there has been at least 2 seconds of no mouse-down events (but mouse must have been clicked at least once for undo saving to happen). That way you can reduce the amount of undo storing, and you wouldn't need to save undo-point in the mouse-down event, which would always make a small lagspike.

  7. #7
    How to properly handle key presses in game?
    After a long break i decided to take another look at adding ped(s) to map editor or any demo i work here.
    But problem is that if i detect the key pressed (either VK_LEFT or RIGHT) or whatever the ped starts moving always with some delay.

    I mean:

    1) I press the up key (forward movement)
    2) It waits for few secs and then starts moving
    3) I release the key and press again..
    4) Again it waits for 1sec or 2 and then starts moving.

    Same with rotating, first the small delay then the rotation.

    Why is that? its in nxpascal code and in my non nxpascal code.
    I have to look how i did it in nxpascal version, ie where i was reading the input..

    EDIT1:
    Ok, i found the src and i handle input in formshortcut event.
    For some reasons in old versions of my editor the gameunit keypressing code didnt work.
    Or stopped working after doing something in graphicsunit or main.pas
    I dont remember.

    How to properly handle input?

    I got the movement to work for ped, i mean with sin/cos and it walks in direction he is looking but the delay at the start of the moving/rotating is really bad.

    In the meantime i will try with fresh src from nxpascal and gameunit keyhandling.

    EDIT2: also it must always move, even if i press rotation key when he is moving. But he stops.

    In my non nxpascal demo i use form.keydown and timer with interval of 16ms.
    Thanks.

    EDIT3:
    As expected, in fresh source and gameunit keyprocessing everything is smooth and nice.
    No delays.
    So i guess keydown/keyup are not for games.


    Actually its mega smooth. Looks so great, i can rotate ped with arrows and walk around, it doesnt stop when rotating and walking at the same time.
    Just like in original game.

    What do you guys think, coldet will be able to get the collisions for me?
    The vertices are so simple and each block face is made of 2 triangles in my vertex data.
    Each slope has own vertices but because many slopes have lids, then lids are same and use same vertices, i dont share them ( i know i could to reduce my vertex data unit size even more, atm its 322KB).

    Coldet had recently a update with useful example.

    Probably not all the blocks on whole map must be checked but only those that are near to the ped. But since my visible are of map is just 15x15 (x,y) blocks + Z maximum 8 blocks i probably could check all these blocks in visible range.
    I dont care about speed atm, i just want quick and dirty to test, if it works, then i will try to make it better.

    It will never probably be full game, i just want to walk around and have collisions.
    Last edited by hwnd; 20-08-2013 at 08:19 PM.

Tags for this Thread

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
  •