【问题标题】:In need for an algorithm for a tile based editor需要基于图块的编辑器的算法
【发布时间】:2016-12-21 05:13:08
【问题描述】:

我目前正在为我的基于磁贴的等距引擎开发磁贴编辑器,并且目前正在研究自动平铺功能。

此时,基于行进正方形算法并使用位掩码,我已经能够计算出正确的角资源以放置在图块类型周围。

一段时间以来,我一直在尝试用较低匹配的瓷砖类型包围特定的瓷砖类型。想一想星际争霸编辑器(Staredit)如何自动围绕具有较低匹配资产的图块类型。

请注意staredit 的这张图片,高草比高泥更重要:

例如,我有 3 个按各自高度排序的资产。认为资产 3 代表高墙,而较低的资产将代表较低的墙。这些资产将被放入元数据中。 0 表示元数据中的一个空图块。

(3,2,1)

首先,3 资产将被放置在用户选择的位置的元数据中。

0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,3,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0

那么 3 资产将被 2 资产包围

0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,2,2,2,0,0,0
0,0,0,2,3,2,0,0,0
0,0,0,2,2,2,0,0,0
0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0

最后,第 2 项资产将被第 1 项资产包围。最终结果应该是这样的。

0,0,0,0,0,0,0,0,0
0,0,1,1,1,1,1,0,0
0,0,1,2,2,2,1,0,0
0,0,1,2,3,2,1,0,0
0,0,1,2,2,2,1,0,0
0,0,1,1,1,1,1,0,0
0,0,0,0,0,0,0,0,0

在此过程之后,将执行自动平铺算法,以便为每个元数据值计算正确的资产/角点。

另一个例子来自这个 HTML5 应用程序。注意墙壁是最高的资产,其次是草,然后是泥土,最后是水。每个资产都被较低的资产包围。 Marching Squares HTML5 Demo

我研究了洪水填充算法,但它似乎不适用于我想要完成的任务。

如果有人对我应该使用什么算法来完成这项任务有解决方案或任何建议,请随时回答这个问题。

我的引擎使用的语言是 Flash As3。

【问题讨论】:

    标签: algorithm actionscript-3 math tiles isometric


    【解决方案1】:

    我正在通过磁贴索引的特定顺序来解决这个问题。看看我使用的瓷砖集:

    该索引还确定每种使用的材料的图块的旋转/角。所以从索引你知道它是哪种材料以及它是哪个位置/旋转。然后,此信息用于自动填充缺失的角落(平滑边缘)。见:

    为了更好地感受这一点,请尝试第一个链接中的演示,并在几个地形图块上使用平滑边缘按钮。

    该算法有点混乱,因为您需要检测缺少哪个角。例如,在我的地形平滑代码中,它看起来像这样:

    int isometric::str_cmp(const AnsiString &a,const AnsiString &b) // wildcard string compare a="01 01" with b="0? 11" for filtering edges in map_random.
        {
        int i; char aa,bb;
        for (i=1;i<=11;i++)
            {
            aa=a[i];
            bb=b[i];
            if ((aa!=bb)&&(aa!=' ')&&(bb!='?')) return 0;
            }
        return 1;
        }
    //---------------------------------------------------------------------------
    void isometric::str_map_diamond  (AnsiString &s,int x,int y,int z)
        {
        s="000 000 000";
        if (y>0)
            {
            if ((x>    0)&&(map[z][y-1][x-1]==16)) s[ 1]='1';
            if (            map[z][y-1][x  ]==16)  s[ 2]='1';
            if ((x<gxs-1)&&(map[z][y-1][x+1]==16)) s[ 3]='1';
            }
            if ((x>    0)&&(map[z][y  ][x-1]==16)) s[ 5]='1';
            if (            map[z][y  ][x  ]==16)  s[ 6]='1';
            if ((x<gxs-1)&&(map[z][y  ][x+1]==16)) s[ 7]='1';
        if (y<gys-1)
            {
            if ((x>    0)&&(map[z][y+1][x-1]==16)) s[ 9]='1';
            if (            map[z][y+1][x  ]==16)  s[10]='1';
            if ((x<gxs-1)&&(map[z][y+1][x+1]==16)) s[11]='1';
            }
        }
    //---------------------------------------------------------------------------
    void isometric::str_map_staggered(AnsiString &s,int x,int y,int z)
        {
        s="000 000 000";
        if ((y>   1)     &&(map[z][y-2][x  ]==16)) s[ 1]='1';
        if (y>0)                                                               
            {                                                                  
            if (int (y&1)==0){                                                 
            if ((x>    0)&&(map[z][y-1][x-1]==16)) s[ 5]='1';
            if             (map[z][y-1][x  ]==16)  s[ 2]='1';                  
            }else{                                                             
            if             (map[z][y-1][x  ]==16)  s[ 5]='1';                  
            if ((x<gxs-1)&&(map[z][y-1][x+1]==16)) s[ 2]='1';                  
            }}                                                                 
            if ((x>    0)&&(map[z][y  ][x-1]==16)) s[ 9]='1';                  
            if             (map[z][y  ][x  ]==16)  s[ 6]='1';                  
            if ((x<gxs-1)&&(map[z][y  ][x+1]==16)) s[ 3]='1';                  
        if (y<gys-1)
            {                                                                  
            if (int (y&1)==0){                                                 
            if ((x>    0)&&(map[z][y+1][x-1]==16)) s[10]='1';                  
            if             (map[z][y+1][x  ]==16)  s[ 7]='1';                  
            }else{                                                             
            if             (map[z][y+1][x  ]==16)  s[10]='1';                  
            if ((x<gxs-1)&&(map[z][y+1][x+1]==16)) s[ 7]='1';                  
            }}
        if ((y<gys-2)    &&(map[z][y+2][x  ]==16)) s[11]='1';
        }
    //---------------------------------------------------------------------------
    void isometric::map_smooth()
        {
        int x,y,z,r;
        AnsiString s;
        map_solid();    // do not work properly on hollow surfaces
        // tile + 8 neighbors -> string "000 000 000"
        void (__closure *_compute_s)(AnsiString &s,int x,int y,int z)=NULL;
        if (map_mode==_isometric_map_mode_diamond  ) _compute_s=str_map_diamond  ;
        if (map_mode==_isometric_map_mode_staggered) _compute_s=str_map_staggered;
        if (_compute_s==NULL) return;
        for (z=gzs-1;z>=0;z--)
            {
            // filter out too small holes
            for (r=1;r;)
             for (r=0,y=0;y<gys;y++)
              for (x=0;x<gxs;x++)
                {
                _compute_s(s,x,y,z);
                     if (str_cmp(s,"??? 101 ???")) { map[z][y][x]=16; s[6]='1'; r=1; }
                else if (str_cmp(s,"?1? ?0? ?1?")) { map[z][y][x]=16; s[6]='1'; r=1; }
                else if (str_cmp(s,"1?? ?0? ??1")) { map[z][y][x]=16; s[6]='1'; r=1; }
                else if (str_cmp(s,"??1 ?0? 1??")) { map[z][y][x]=16; s[6]='1'; r=1; }
                }
            // smooth edges
            for (y=0;y<gys;y++)
             for (x=0;x<gxs;x++)
                {
                _compute_s(s,x,y,z);
                     if (str_cmp(s,"?1? ?01 ???")) map[z][y][x]= 9;
                else if (str_cmp(s,"??? ?01 ?1?")) map[z][y][x]=10;
                else if (str_cmp(s,"??? 10? ?1?")) map[z][y][x]=11;
                else if (str_cmp(s,"?1? 10? ???")) map[z][y][x]=12;
                else if (str_cmp(s,"??? ?01 ???")) map[z][y][x]= 5;
                else if (str_cmp(s,"??? ?0? ?1?")) map[z][y][x]= 6;
                else if (str_cmp(s,"??? 10? ???")) map[z][y][x]= 7;
                else if (str_cmp(s,"?1? ?0? ???")) map[z][y][x]= 8;
                else if (str_cmp(s,"?01 ?00 ???")) map[z][y][x]= 1;
                else if (str_cmp(s,"??? ?00 ?01")) map[z][y][x]= 2;
                else if (str_cmp(s,"??? 00? 10?")) map[z][y][x]= 3;
                else if (str_cmp(s,"10? 00? ???")) map[z][y][x]= 4;
                }
            // fill space below slopes to avoid artifacts
            if (z)
            for (y=0;y<gys;y++)
             for (x=0;x<gxs;x++)
              if (map[z][y][x]>0)
               map[z-1][y][x]=16;
            }
        _redraw=true;
        }
    //---------------------------------------------------------------------------
    

    16 是地形砖,{ 0,..,11 } 是旋转和连接砖。更多参考这里是旧源代码,这是基于:

    代码只是将处理后的地图位置(图块)的 8 个邻居转换为字符串,其中0 表示空位置,1 表示存在地形块(16)。然后应用掩码比较来检测每个缺少角/连接块的情况。

    您可以对每种支持的材料进行类似的操作...

    【讨论】:

      【解决方案2】:

      我发现这样做的最佳方法是使用 BFS 或 Dijkstra 自动平衡地图数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-05
        • 1970-01-01
        • 1970-01-01
        • 2013-02-08
        • 2023-03-21
        • 1970-01-01
        • 2015-12-13
        • 1970-01-01
        相关资源
        最近更新 更多