Page 5 of 9 FirstFirst ... 34567 ... LastLast
Results 41 to 50 of 87

Thread: Space Shooter Game Editor

  1. #41
    Hello,

    I was drawing tiles for the last few days...damn it sure takes a lot of time...and then it's still , I don't know , not good enough.

    Anyway today I've decided to modify the mouse cursor thing, and I was playing with the AthorPanel... and I've realized, that we don't even need , on mouse enter or on mouse leave, or MyMouse valid for that matter, this is what I did :

    Code:
     procedure TMain.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    begin
      if (MyMouse.Position.X < Panel1.Width) and (MyMouse.Position.Y < Panel1.Height) then    // Mouse can only go till edge of Panel1
        begin
          MyMouse.Position:=Mouse.CursorPos;   // I get mouse cursor position
          dec(myMouse.Position.X, Left+Panel1.Left+Panel2.Width); // I remove from the cursor position
          dec(myMouse.Position.Y, Top+Panel1.Top+Panel4.Height);
        end
      else
        begin
          MyMouse.Position.X:=MyMouse.Position.X-1;  // once it reaches edge , in order not to get stuck... I decrease it's value by 1
          MyMouse.Position.Y:=MyMouse.Position.Y-1;
        end;
    end;
    And on AsphyreDevice render

    Code:
      // get position on map, for example 2;4  , but only if x < 20 and y < 15 , the myMouse.valid was not enough to prevent it from happening
      if (floor(myMouse.Position.X / (Panel1.Width / 20 )) < 20) and (floor(myMouse.Position.Y / (Panel1.Height / 15 )) < 15 ) then
        begin
          map_x_pos:=floor(myMouse.Position.X / (Panel1.Width / 20 ));
          map_y_pos:=floor(myMouse.Position.Y / (Panel1.Height / 15 ));
          Label16.Caption:=inttostr(map_x_pos)+','+inttostr(map_y_pos);
          with Selection do
            begin
                X:=map_x_pos*32;
                Y:=map_y_pos*32;
            end;
        end;
    Does the same thing, + better , this way I NEVER-EVER leave the grid, sometimes with previous versions it was possible to leave the grid... the Selection cursor dissapeared, and your position was X:=20, or Y:=15 for example.

    Greetings
    Robert

  2. #42
    Damn,

    My last post was heavily bugged, damn, I was using Panel OnMouse move, and I don't know how the heck did I not see it provides X,Y...
    Code:
    procedure TMain.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    begin
      MyMouse.Position.X:=X;
      MyMouse.Position.Y:=Y;
    end;
    On Device Render
    Code:
      map_x_pos:=floor(myMouse.Position.X / (Panel1.Width / 20 ));
      map_y_pos:=floor(myMouse.Position.Y / (Panel1.Height / 15 ));
      Label16.Caption:=inttostr(map_x_pos)+','+inttostr(map_y_pos);
      with Selection do
        begin
          X:=map_x_pos*32;
          Y:=map_y_pos*32;
        end;
    Now I only need to make the logic if I keep the mouse pressed it should draw the last tile... say I wanna draw land tiles for say 20 screens, it wont do clicking one-by-one.

    Greetings
    Robert

  3. #43
    Quote Originally Posted by robert83 View Post
    Now I only need to make the logic if I keep the mouse pressed it should draw the last tile... say I wanna draw land tiles for say 20 screens, it wont do clicking one-by-one.
    Notice that Shift is also provided. It can tell if left mousebutton is down. Just throwing some code, might or might not be what you are after
    Code:
    procedure TMain.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    begin
      MyMouse.Position.X:=X;
      MyMouse.Position.Y:=Y;
      ScreenToWorldCoords(X, Y);
      if ssLeft in Shift then begin
        FillTile(trunc(worldX), trunc(worldY), Pattern);
      end;
    end;

  4. #44
    Hello,

    Thank you! I did it. For the mouse click part I mean.

    Anyway I was going a bit further as per SilverWarrior's ideas, my next step is the grid where I can have different sized tiles . I made a drawing about how I thought I'd make it.

    My thoughts :

    1. I was looking at multiple TILE based editors and all of them had some sorta base tile , which I think if I'm right is the MINIMUM tile size possible on the map, say 32x32 is minimum, but I can have up to say 256x256 tiles for example.
    2. Even though I will have multiple sized tiles , and the possiblity that say layer 15 will only have like 10 entires , I'm still sticking to the dynamic array right ? ( probably I don't want to go there right now, ... but how much memory am I
    "wasting" with a layer 15 array that is 20x150 and has only 10 entries , meaning the other 2990 are there for nothing , is Delphi "smart" here and is not allocating memory for non used array entries?
    3. With this idea I would put images larger then 32x32 into the ASDB file like this , 128x128 example : Texture Size : 128x128, Pattern Size : 32x32 ... when I would put the image into the array I would use a for cycle to put the apropriate
    Patterns into the apropriate array entries... something like this :
    Code:
    procedure TMain.PlaceTile;
    var x,y,pattern : integer;
    begin
      pattern :=1;  // here I reset pattern count to 1
      If EditorInitialized = true then
        begin
          for y:= map_y_pos to (Images.Image[ListView1.Items[ListView1.ItemIndex].Caption].Size.Y div Images.Image[ListView1.Items[ListView1.ItemIndex].Caption].PatternSize.Y) do  // I go from cursor position till image bottom
            begin
              for x:= map_x_pos to (Images.Image[ListView1.Items[ListView1.ItemIndex].Caption].Size.X div Images.Image[ListView1.Items[ListView1.ItemIndex].Caption].PatternSize.X) do // I go from cursor position till image right edge
                begin
                  map.Lines[y+Offset,x].ImageName:=ListView1.Items[ListView1.ItemIndex].Caption;  // I need to know image name  (will probably revert back to Index )
                  map.Lines[y+Offset,x].PatternNo:=pattern;  // I need to know pattern index
                  inc(pattern,1);
                end;
            end;
    (the above code is partly from head , so there is a probability that It will not to what I think it should do , will test it later though )
    This way I would still need to draw Sprites for one screen , but could have any tile sizes in them above 32x32 till say 256x256 ( 512x512 to big... because my screen is 640x480 for this project , I don't want to overwhelm myself )
    With minor adjustment my current draw procedure could handle this and the scrollmap procedure as well (atleast I think so... did not go start fidling with the code itself...)

    The only setback which is probably a huge one, that I need to create full sprite engine sheet for each layer LayerN * 301 .

    UPDATE : I need to change my AnimCount to take data from TextureCount instead of PatternCount ( was wrong in using PatternCount in the first place probably...) , I tested this when adding a 128x128 file to the
    asdb database , 128x128 Tile, PatternCount 6, Texture Count 1 ....

    UDPATE 2 : another error I made everywhere, I've just noticed that I must make my textures with sizes like this : 128x128 ( here I have 1 texture, 16 patterns) then 128x256 (here I have 2 texture , 32 patterns ) , if I do it like this 256x128 ... I get mixed up lines...
    and if I make an animation I must place every new texture bellow the original, not like I'm doing it now to the right....

    --------------------------------------------------------------------------------------------------------------------------

    My other idea was, based on a LevelEditor found on the Asphyre forums (the old one...) , is to create the Sprite 's on demand, but my problem is I don't know how could I mix that combo with a dynamic array. In that editor the user clicks
    anywhere on the map, and a tile is created in that position, with apropriate size (be it 32x32, 128x128, 256x256....) , the only thing is that , that map editor does not use array to store map data it uses LevelStruct record and it writes it to a file of TLevelStruct and reads it that way. Which is fine but I have a few problems with it I don't know how to solve :

    1. I place a tile on the map with Z:=0 , I place another tile on top of this Z:=1 , Z:=2 , Z:=3 ... without the array how do I tell the program that I want to delete (replace) only Tile at Z:=1 ? The LevelEditor uses OnCollision to detect if the cursor is on a certain sprite, but I don't know how well it works if I have in worst case scenario tiles that overlap.... ground bellow, then flowers, and tree above for example.
    2. Also with this Editor, without the array I need to create all the sprites ... ( side note : or maybe I could read them from the file line by line ? use the file , kinda like an array ? hmmm....)
    3. Scrolling I think would not be problematic.... I could scroll same way and destroy the Sprite if it's Top is out of the screen ( example tree 128x128, I kill it if it's completely outside of screen )

    I'm not sure which way to go, anyway I thought I'd share my ideas here, for you to comment and for me to remember, right now I'm kinda stuck.

    Greetings
    Robert
    Attached Images Attached Images
    Last edited by robert83; 24-01-2013 at 12:25 PM. Reason: TextureCount instead of PatternCount for AnimCount

  5. #45
    You only need 1 patternwidth,height for 1 image, in your case that 32x32 can be fine. If you need a big 200x190 odd sized sprite, you can use a separate image for it. But if you want to use the 32x32 image for bigger combinations, you don't need anything special for the drawing engine. Plotter would just insert in 64x64 sprite case all 4 of those 32x32 patterns to world tile grid. That is only the editor application's concern. I know it's not going to be too easy, to program editor to behave like that. Have to make sort of map file for each pattern image, to describe the areas.

    There is another sort of "areas" in tiles too:
    - Random variations of each tile.
    - Turning tiles... For example when making room, you can have 16 different kind of patterns (straight vertical, straight horizontal, 4 corners, 4 ends, 1 lonely tile, 1 tile surrounded by 4, and 4 "T" sections). Most tile editors go with the lazy way, and tell map maker to select the different tile himself. But smart program tells you to use just 1 tile, and paint the whole wall with it, selecting the right pattern automatically. I have done this before, it's complicated but i can give 1 sort of hint:
    Pattern description for top left corner could be:
    Code:
    ?xx
    x##
    x#?
    ...where (? is any pattern, # is same pattern and x is different than #). You can make similar filter for every pattern type, for automatic selection.
    Last edited by User137; 24-01-2013 at 12:11 PM.

  6. #46
    I'm trying to implement the following correctly :

    Put 32,64,128,256 x 32,64,128,256 Sized Tiles on my Map... right now I can put it on map... but it's not handled correctly because in my Grid I assume each tile is 32x32... so if I create a 64x64 tile , the following happens [see image for better understanding]

    Array is updated but only the top,left corner has the data for the tile... while the other 3 have no data... and for example if I scroll down...and the first tile is not visible the entire 64x64 tile dissapears, or if I try to place a regular 32x32 tile to it's bottom right corner it wont be
    visible ...


    I think I should somehow maybe draw parts of the image ?

    0,0 first part , 0,1 second part
    1,0 third part, 1,1 fourth part

    But I don't know how to do this ... (or for that matter if it's the right move)

    Inside the asdb database the image I'm playing right now with is 64x64 in size.

    Greetings
    Robert
    Attached Images Attached Images
    Last edited by robert83; 24-01-2013 at 03:41 PM.

  7. #47
    Robert first of all I'm sorry that I haven't done much work in the past few days but I do have some real life isues at the moment.

    Quote Originally Posted by robert83 View Post
    Anyway I was going a bit further as per SilverWarrior's ideas, my next step is the grid where I can have different sized tiles . I made a drawing about how I thought I'd make it.
    My idea was that different layers use different tile sizes but still each layer can only contain tiles of the same size. For instance you have layer1 with tiles 32x32 in size but layer2 has tiles 64x64 in size. None of the layers actually has 32x32 and 64x64 sized tiles at the same time.


    Quote Originally Posted by robert83 View Post
    Even though I will have multiple sized tiles , and the possiblity that say layer 15 will only have like 10 entires , I'm still sticking to the dynamic array right ? ( probably I don't want to go there right now, ... but how much memory am I
    "wasting" with a layer 15 array that is 20x150 and has only 10 entries , meaning the other 2990 are there for nothing , is Delphi "smart" here and is not allocating memory for non used array entries?
    Array is just one continuos block of memory containing all the data of its items.
    The only difference between dynamic and static array is that static array has fixed size and mumber of items it can contain right after its creation while dynamic array can be resized at runtime. S
    Memory requred for each of theese array types is number of array items multiplied by item size.


    Quote Originally Posted by robert83 View Post
    The only setback which is probably a huge one, that I need to create full sprite engine sheet for each layer LayerN * 301 .
    Not necessarely. You create only those sprites that are needed. It would be useles creating empty sprites in upper layers.


    Anywhay I plan on replacing your arrays of records with Lists and objects. Why?
    List is actually just a managed array of pointers. Theese pointers then point to object, varibales or, records of data to be used. In our case I was planning of using TObject list which only contains pointers to TObjects.
    So mapdata would actually be stored in bunch of objects which would replace TTile record. Then you would have one TObjectList for each line and finally one TObjectList for each layer.
    As list only use pointers you can actually have list with 100 of items where only 10 of them point to 10 different objects and rest of them are set to nil.
    This would mean that in this case you would use 100 * 32 bit of data for storing TObjectLists data and 10 * size of object to store actually data required for needed tiles.
    And the best thing is that you can actually have several TObjectList items to actually point to the same object meaning that you would actually need only so many object as the number of posible tiles.
    So if your game have 100 of different textures you would only need 100 of objects even if your map would have 100 tiles width and 10000 tiles of height. Actually in above example you would need:
    100 objects
    10000 of TObjectList storing data for each line while each of this TObjectLists would have 100 items (pointers) to point to necessar data for each line.
    and one object list which would actually point to those other TObjectLists representing data for each line.
    And if one of your layers don't need any tile rendered in certain line this means that you won't even need TObjectList representing data to that line and TObjectList representing whole map data would have one boject which would othervise point to that line data set to nil.

    I hope I will have more time in the next few days to put all this into code. I will try to do this in a way so that it would be easily used as posible and ofcourse write a documentation thourally explaining how this actually works.

  8. #48
    Class objects (TObject) are way of making code "object oriented", or sometimes more readable for us humans. However they have a drawback that it will take more memory, and be slower than traditional arrays, records and pointers.
    1 TObject takes some memory. First it has the reference "pointer" which is 4 or maybe 8 bytes on 64-bit systems. Then there is TObject's internal data, and finally user data.

    If i'd have to make tile-based game with 10000 different textures (absurd in first place, because lots texture switching puts huge stress on rendering speed), i would have tile indexes in a dynamic array, and another array just for the information for each index. Like:
    Code:
    type
      TIndexInfo = record
        pattern, texture: word;
      end;
      PIndexInfo = ^TIndexInfo;
    
      TTile = packed record
        index: word;
      end;
    
    indexInfo: array of TIndexInfo;
    tiles: array of TTile;
    Code:
    function GetTileInfo(x, y: integer): PIndexInfo;
    begin
      if ...x, y in valid range... then // range check if possible to call this outside of map boundaries
        result:=@indexInfo[tiles[x+y*MapWidth].index];
    end;
    So each tile takes 2 bytes of memory, if you don't define other tile specifics into TTile. indexInfo array must be initialized at program start too, for each texture and pattern present.

  9. #49
    Quote Originally Posted by User137 View Post
    If i'd have to make tile-based game with 10000 different textures (absurd in first place, because lots texture switching puts huge stress on rendering speed), i would have tile indexes in a dynamic array, and another array just for the information for each index. Like:
    I wasn't talking about having 10000 different textures (who would take the time to make all theese) but instad I was talking about having the map size where its height is 10000 tiles (map width is othervise 19 tiles if I recal corectly).
    I was actually talking about having 100 different posible textures and not 10000.


    Quote Originally Posted by User137 View Post
    TObject takes some memory. First it has the reference "pointer" which is 4 or maybe 8 bytes on 64-bit systems. Then there is TObject's internal data, and finally user data.
    I'm aware of that.
    The reason why I plan to use TObjects is to gain advantage of using its properties. If you recal we also talked about the way of syncrhronizing tile animations. I plan on doing this in a way that each TObject which would be representing certain tile would also contain pointer to another TObject which would represent animation information (animation lenght, speed, etc).
    Sure you could do this using records but then you need to have code similar to this:
    Code:
    Tile.Animation.Speed
    But I was thinking of doing this something like this.
    Code:
    type
      TAnimation = class(TObject)
      private
        FSpeed: Single; //Defining animation speed
        FCount: Integer; //Defining the number of frames animation has
        FOffset: Integer; //Defining on which frame does animation starts
        FPosition: Integer; //Defining current animatiomn position
      protected
        procedure SetSpeed(AValue: Single);
        procedure SetCount(AValue: Integer);
        procedure SetOffset(AValue: Integer);
        procedure SetPosition(AValue: Integer);
      public
        property Speed: Single read FSPeed write SetSpeed;
        property Count: Integer read FCount write SetCount;
        property Offset: Integer read FOffset write SetOffset;
        property Position: Integer read FPosition write SetPosition;
      end;
      TTile = class(TObject)
      private
        FTexture: Integer; //Defining which image to use
        FAnimationParam: TAnimation; //Object storing animation parameters
      protected
        procedure SetTexture(AValue: Integer);
        procedure SetAnimationParam(AValue: TAnimation);
        function IsAnimated: Boolean;
        function GetAnimationParam: TAnimation;
        function GetAnimationSpeed: Single;
        function GetAnimationCount: Integer;
        function GetAnimationOffset: Integer;
        function GetAnimationPosition: Integer;
      public
        property Texture: Integer read FTexture write SetTexture;
        property AnimationParameters: TAnimation read GetAnimationParam write SetAnimationParam;
        property AnimationSpeed: Single read GetAnimationSpeed;
        property AnimationCount: Integer read GetAnimationCount;
        property AnimationOffset: Integer read GetAnimationOffset;
        property AnimationPosition: Integer read GetAnimationPosition;
        property Animated: Boolean read IsAnimated;
      end;
    Code:
    function TTile.GetAnimationParam: TAnimation;
    begin
        result := nil;
        if FAnimationParam <> nil then
        result := FAnimationParam;
    end;
    function TTile.GetAnimationPosition: Integer;
    begin
        if FAnimationParam <> nil then
        result := FAnimationParam.Position;
    end;
    
    function TTile.IsAnimated: Boolean;
    begin
        result := False;
        if FAnimationParam <> nil then result := true;
    end;
    
    procedure TTile.SetAnimationParam(AValue: TAnimation);
    begin
        FAnimationParam := AValue;
    end;
    NOTE: Code is writen from my head so it is posible to contain errors. Also it isn't a compleete - several class methods are still missing so it won't work as such.

  10. #50
    Thank you guys, obviously I misunderstood , and since my knowledge is limited on this field, I've almost went on the wrong road, by trying to somehow enable the usage of different sized tiles on the same layer (probably possible, but is faaar beyond my current level I think, and for a first project I think I need not over complicate) . So I think once I figure out how to properly create only needed sprites with my current array setup... I'll try using that approach, layer 1 custom size 32x32 ,64x64,128x128 etc...

    Oh and no problem , I'm very greatefull for you taking your time and replying giving great advices, help. Thank you!

    Meanwhile since I could not sit idle.... I did a little further coding , added aditional layers , right now for my convinence I've made it fixed, I have 4 layers... I can edit, all of the layers have 310 sprites... which I later tend to fix, I just wanted to make something work, so I can feel like, I did something.

    Anyway I'm attaching the source, if you'll take a look, you probably notice a lot of commented lines in my scrollmap part. I've actually had a brainstorm, and realized how I can create only needed tiles, I even went as far as to only move
    existing tiles in the array , my only problem is as you see, since I'm only moving Tiles that are not NIL, I'm also limiting myself to creating tiles that were not nil previously... , will need to rethink my logic there, but I'm think I'm close to solving the problem to only display as many sprites as I need, not 4*310. Also I've noticed one strange thing here, I need to specificaly go trough the array and NIL those entires that have no BackGround Sprite... otherwise something is left there which is not a BackGround Sprite, but is not NIL either. Probably gona have to watch out for this in the future, and do a for cycle to clean dynamic arrays with NIL .

    I've also fixed the mouse, it's now properly implemented, tough it has one problem which I will fix later... I'm allowing user to place tiles when the mouse button is pressed down on panel move... this works great...but is executing the command to many times uneaded... I will need to probably get current mouse position store it, and then only place new tile and update the screen if I moved mouse from previous position in either direction by tile width or height (if not 32x32, but 64x32 or something else).

    I've also changed to use TMemoryStream instead of TFileStream. And fixed a few possible bugs in the SaveLevel and LoadLevel procedure , sizes were not set properly...

    One HUGE bug I have is, if you click on the TListView where is no TILE and then CLICK on the MAP , you get an access violation, will look into this later.

    The tileset I'm using right now is not mine, it's from a free site providing awesome tiles.

    Attached my project full source + map included, you can load the map, and then press the test button to test it.

    In the meanwhile I'm gona look up and study TObjectList , TList , I've actually heard of it in another TILE MAP editor howto for BASIC I think pretty old one... the guy who wrote it mentioned that it's smarter to use ObjecList because of
    the fact that storing layers on array is a waste of space , because not all layers will actually be completely filled, infact probaly none of the layers will be 100% filled, maybe the first...


    Greetings
    Robert
    Attached Files Attached Files

Page 5 of 9 FirstFirst ... 34567 ... 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
  •