2016-08-14 10 views
3

В настоящее время я разрабатываю редактор плит для моего изометрического движка на основе плитки и в настоящее время работаю над функциями автоматического черепицы.Необходим алгоритм для редактора на основе плитки

На этом этапе, основываясь на алгоритме маршевых квадратов и использовании битовой маски, я смог вычислить правильные угловые активы для размещения вокруг типа плитки.

В течение некоторого времени я пытаюсь окружить конкретный тип плитки нижним соответствующим типом плитки. Подумайте, как редактор Starcraft (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 

После этого процесса алгоритм autotiling будет выполняться для того, чтобы вычислить правильные активы/углы для каждого значения метаданных.

Другой пример этого будет из этого приложения HTML5. Обратите внимание, как стены являются самыми высокими активами, за ними следуют трава, затем грязь и, наконец, вода. Каждый актив окружен более низким активом. Marching Squares HTML5 Demo

Я изучил алгоритм заполнения заливки, но кажется, что это не относится к тому, что я пытаюсь выполнить.

Если у кого-то есть решение или какой-либо совет по алгоритму, который я должен использовать для выполнения этой задачи, не стесняйтесь отвечать на этот вопрос.

Язык, который я использую для моего двигателя, - Flash As3.

ответ

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 } являются севообороты и присоединиться кирпичи. Для получения дополнительной референс здесь oldersource кода это было основано на:

Код просто преобразует 8 соседей переработанного положения на карте (плитка) в строку, где 0 означает пустое место и 1 означает кирпич местности (16) есть. Затем маскированное сравнение применяется для обнаружения каждого случая отсутствия угла/соединения.

Вы можете сделать это аналогично для каждого материала, поддерживаемого ...

 Смежные вопросы

  • Нет связанных вопросов^_^