需要基于图块的编辑器的算法

时间:2016-08-14 23:42:57

标签: algorithm actionscript-3 math tiles isometric

我目前正在为基于磁贴的等轴测引擎开发一个磁贴编辑器,目前我正在开发自动平铺功能。

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

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

关于这张图片的注意事项,从staredit看,高草是一种更高的资产,然后是高污垢:

1

例如,我有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。

1 个答案:

答案 0 :(得分:1)

我通过tile索引的特定顺序解决了这个问题。看看我使用的瓷砖组:

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

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

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

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 }是旋转和连接砖。有关更多参考,请参阅以下内容的oldersource代码:

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

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