Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Tilemaps and autotiles

  1. #1

    Tilemaps and autotiles

    RPG Maker has nice feature called Autotiles. Those tiles are made so one tile can be shrinked to as small amount as 3x3 tile square plus one tile with cramped corners.

    Example autotile

    Top-left tile is used only as display of tile in editor, top right contains inside corners of tile. 3x3 tiles square contains outside corners, sides and middle of tile.

    Here are tiles that can be made out of this:


    (I'm using unofficial Polish translation of RPG Maker XP so title is because of that).

    I have pretty much idea how I can break up autotiles and make all those tiles. Problem is another one - how I choose "right" tile so they'll fit together in map?

    Let's assume that in following code "0" represent normal tile and "1" autotile. I want to display them properly:
    Code:
    0 0 0 0 0 1 0 0 0 0 0 
    0 0 0 0 1 0 0 0 1 0 0
    0 0 0 0 1 1 1 0 1 0 0
    0 0 0 1 1 1 1 0 1 1 0
    0 0 0 0 0 1 0 0 0 1 0
    0 0 0 1 1 1 1 1 1 1 0
    How can I achieve this?

  2. #2
    I used to check all eight adjacent tiles if they are the same type or not, and then draw the autotile accordingly. I had two variables, one for sides, one for corners. Each of them was actually kind like a 4-bit flag. I set them according to the adjacent tiles, and then I had a huge (16-element, duh) case of sides_variable. Like, if no adjacent autotiles, draw the "single spock", if only one adjacent autotile, draw the connecting gfx on one half, and on the other half draw corners (which can be either inside or outside facing).

    If you'd like, I can share some code, but you'll have to give me some time to add comments et cetera so it can be readable.

  3. #3
    Sure! Will wait.

  4. #4
    Instead of posting actual code, I think I'll just describe the logic I used.

    First of all, this code was designed to use a different format of autotiles, like this:

    5 tiles placed horizontally: full tile, top & bottom border, left & right border, outside corners, inside corners.

    Code:
    // Bit flags for sides and corners.
    const SIDE_TOP = 1; SIDE_BOT = 2; SIDE_LEF = 4; SIDE_RIG = 8;
            COR_TL = 1; COR_TR = 2; COR_BL = 4; COR_BR = 8;
    
    // I assume map to just hold integers with tile types
    Procedure DrawMapTile(X,Y : Integer; Gfx : whatever)
    Var Edges, Corners : Integer;
    begin
    Edges := 15; Corners := 15; // All flags set means that autotile is stranded and we have to draw borders.
    If (Y = 0) or (Map[X][Y-1] = Map[X][Y]) then Edges -= SIDE_TOP; // We mark top side as no-border
    If (Y = (MapH-1)) or (Map[X][Y+1] = Map[X][Y]) then Edges -= SIDE_BOTTOM; // We mark bottom side as no-border
    // The same for left
    // The same for right
    If (X = 0) or (Y = 0) or (Map[X-1][Y-1] = Map[X][Y]) then Corners -= COR_TL; // We mark top-left corner as the same type
    // Same for top-right
    // Same for bottom-left
    // Same for bottom-right
    Case Edges of
    00: begin // 00 means that all sides are connected. We either have to draw a full tile or an all inside-corners tile.
        DrawFullTile(X,Y);
        DrawCorner(X,Y,Corners,COR_TL);
        DrawCorner(X,Y,Corners,COR_TR);
        DrawCorner(X,Y,Corners,COR_BL);
        DrawCorner(X,Y,Corners,COR_BR)
        end;
    01: begin // 01 means that there is a border on the bottom side.
        DrawBorder(X,Y,Edges,SIDE_TOP);
        DrawBorder(X,Y,Edges,SIDE_BOT);
        DrawCorner(X,Y,COR_TL);
        DrawCorner(X,Y,COR_TR);
        end;
    Et cetera, et cetera. Edges can be 00-15, so you have 16 cases. DrawBorder() should check if the appropriate edge (SIDE_XXX) flag is set in Edges, and either draw a border or draw the connecting part of tile. DrawCorner() behaves the same way.

    This approach requires much copy-pasta and introduces some over-draw, but I've found the easiest to implement in terms of logic.

  5. #5
    Well, 16 tiles aren't enough.

    Sure, you could do tile like this:
    Code:
    -------
    |######
    |######
    |######
    or this:
    Code:
    -------
    #######
    #######
    #######
    But how about this:
    Code:
    --------
    |######|
    |######|
    |######|
    or this:

    Code:
    ------
    ######
    ######
    ------
    ? I know you know RPG Maker because I know you from Polish RPG Maker forum, even you are using same avatar. I want solution like in case of RPG Maker.

    Also I've said that I have no problem with breaking autotile into individual tiles, main problem is getting "right" "sub tile" for the job.

    //edit: Anyway, I've decided that I'll write "breaker" program that would break autotile into individual tiles and output it into image file. Then in map editor I'd place them manually. Would save myself coding pain.
    Last edited by Darkhog; 11-07-2013 at 10:03 PM.

  6. #6
    It's not limited to 16 tiles, you can do all the shapes an autotile can have on a square map.
    Code:
    -------
    |######
    |######
    |######
    Edges = 5 (top + left). Draw left border, top border, top-left outside corner, and then either a continuous tile or inside corner in bottom-right.
    Code:
    -------
    #######
    #######
    #######
    Draw top border. Bottom side, each quarter-tile is either continuous or an inside corner.
    Code:
    --------
    |######|
    |######|
    |######|
    Draw left, right border, and top inside corners.
    Code:
    ------
    ######
    ######
    ------
    Draw top and bottom border.

    If you forget about the "continuous or inside corner" issue, you only have 16 possible tiles - depending on the four neighbouring tiles: top, bottom, left and right. That's why I wrote about 16 cases. In the cases I draw borders and outside corners, because they depend only on those 4 tiles.
    Code:
    x----
    -Xxx
    -xxx
    We can tell the "big X" must have an outside corner at the top-left, no matter if the (X-1,Y-1) tile is of the same type, or not. So, like I said, checking the 4 neighbours gives me 16 cases, and in every case I know exactly which borders and inside corners I have to draw. Then I only need to check if any of the remaining quarters of the tile should be continuous or have an inside corner.


    If it still sounds bizarre, give me a day and I'll write you an example.

  7. #7
    I'm writing yet another project, which also uses autotiles. The result looks like this:

    If you're still interested, I can post a sample program here.

  8. #8
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25
    Here is an old "guide" that I made for my current game project some years ago.

    Wallset_Wall_Explanation.jpg

    The tiles aren't used quite exactly the same way. It was more meant for walls instead of your typical RPG map tiling. However it shows all the checks to select a tile from a list of 47 individual case scenarios you would encounter.

    The basic idea was to check your 4 cardinal directions and if a wall (or in your case tile of the same type) was detected in 2 tiles beside a corner it would check that corner too.

    Not sure if this would be of any help, but it sort of relates so it might give you other ideas of just confuse. Enjoy! lol
    Jason McMillen
    Pascal Game Development
    Co-Founder





  9. #9
    Hm, that chart helps a lot. Thanks!

    @Super Vegeta, sure, post it!

  10. #10
    I will try to post my idea of how to solve this shoretly I hope.

    Anywhay in my idea you have numerical property which tels you which sprite you need to use for that tile. Since you are afecting this number by changing seperate bits of this numerical variable (each bit represents each side and each corner) there will be no need to use any logical system for constantly figuring out which sides/corners of your current sprite are neighboring to other wall sprite for instance. Since the system uses 8 bit integer (byte) for determining autotile you have 256 posible options for each cell.

    Now I'm currently testing different aproaches for changing seperate bits of this numerical variable to see which is best and safest. I'll try to make it thread safe so it can be easily used in multithreading applications.

    I hope I will be able to write you full solution example this weekend.

Page 1 of 2 12 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
  •