Елегантна автоматизація


10

Я шукаю інформацію про те, як люди впроваджують автоматичне використання у своїх іграх на основі плиток. Поки я завжди імпровізував це з купою твердо кодованих висловлювань "якщо ... ще ...", і тепер я вирішив, що настав час знайти якесь більш елегантне рішення. Я пішов шукати в Інтернеті приклади реалізацій автотилізації та обговорення на цю тему, але придумав лише три статті:

(Особливо останній є всеосяжним та дуже корисним.)

Я також переглянув різні реалізації та документацію бібліотек, які реалізують її, наприклад, flixel: http://www.flixel.org/features.html#tilemaps

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

Я шукаю елегантний приклад реалізації автоматичної автоматизації, з якого я міг би навчитися.

Відповіді:


10

Я використав побитовий метод нанесення Tilemaps і виявив, що це дуже елегантне рішення. У статті наводиться конкретний приклад та розглядаються способи розширення алгоритму для обробки декількох типів рельєфу.


Це виглядає так, як алгоритм, що використовується в режимі автоматичного ввімкнення "AUTO". Дякую, я додаю його до свого списку.
Радомир Доперальський

3

Я сам приїхав сюди, гуглюючи цю проблему, прочитав пов'язані статті та створив відносно компактне рішення, яке генерує загальний набір із 47 плиток. Для матеріалу з автоматичним набором потрібен набір плиток 2x3:автоматичний набір плиток 2x3

З варіантом з однією плиткою у верхньому лівому куті, внутрішніми кутами вгорі праворуч та чотирма зовнішніми кутовими плитками внизу (ви можете розпізнати цю композицію від виробника RPG).

Хитрість полягає в тому, щоб розбити кожну "логічну" плитку на карту на 4 півплітки для візуалізації. крім того, напівлитка в наборі плиток може знаходитись лише в такому положенні у створеній плитці, тому верхню ліву половину плитки можна використовувати лише у верхньому лівому положенні.

Ці обмеження означають, що вам потрібно перевірити лише 3 сусіди з повною плиткою на половину плитки замість усіх 8 сусідніх плиток.

Я реалізував цю ідею швидко, щоб перевірити її. Ось код підтвердження концепції (TypeScript):

//const dirs = { N: 1, E: 2, S: 4, W:8, NE: 16, SE: 32, SW: 64, NW: 128 };
const edges = { A: 1+8+128, B: 1+2+16, C: 4+8+64, D: 4+2+32 };
const mapA = { 0:8, 128:8, 1:16, 8:10, 9:2, 137:18, 136:10, 129:16 };
const mapB = { 0:11, 16:11, 1:19, 2:9, 3:3, 19:17, 18:9, 17:19 };
const mapC = { 0:20, 64:20, 4:12, 8:22, 12:6, 76:14, 72:22, 68:12 };
const mapD = { 0:23, 32:23, 4:15, 2:21, 6:7, 38:13, 34:21, 36:15 };

export function GenerateAutotileMap(_map: number[][], _tile: integer): number[][]
{
    var result = [];
    for (var y=0; y < _map.length; y++) {
        const row = _map[y];
        const Y = y*2;
        // half-tiles
        result[Y] = [];
        result[Y+1] = [];
        // each row
        for (var x=0; x < row.length; x++) {
            // get the tile
            const t = row[x];
            const X = x*2;
            if (t != _tile) continue;
            // Check nearby tile materials.
            const neighbors = (North(_map, x, y) == t? 1:0)
                + (East(_map, x, y) == t? 2:0)
                + (South(_map, x, y) == t? 4:0)
                + (West(_map, x, y) == t? 8:0)
                + (NorthEast(_map, x, y) == t? 16:0)
                + (SouthEast(_map, x, y) == t? 32:0)
                + (SouthWest(_map, x, y) == t? 64:0)
                + (NorthWest(_map, x, y) == t? 128:0);
            // Isolated tile
            if (neighbors == 0) {
                result[Y][X] = 0;
                result[Y][X+1] = 1;
                result[Y+1][X] = 4;
                result[Y+1][X+1] = 5;
                continue;
            }
            // Find half-tiles.
            result[Y][X] = mapA[neighbors & edges.A];
            result[Y][X+1] = mapB[neighbors & edges.B];
            result[Y+1][X] = mapC[neighbors & edges.C];
            result[Y+1][X+1] = mapD[neighbors & edges.D];
        }
    }
    return result;
}    

Пояснення:

  • Aє лівою верхньою частиною плитки, Bправою верхньою, Cнижньою лівою, Dправою нижньою.
  • edges містить біт-маски для кожного з них, тому ми можемо захопити лише відповідну інформацію про сусід.
  • map* є словниками, які відображають сусідні стани з графічними індексами у наборі фрагментів (0..24).
    • оскільки кожна половинка перевіряє 3 сусідів, кожен має 2 ^ 3 = 8 станів.
  • _tile - це плитка, орієнтована на автотилізацію.
  • Оскільки наші логічні плитки вдвічі більше, ніж наші плитки візуалізації, всі карти автотилів (x, y) повинні бути подвоєні на карті візуалізації.

У будь-якому випадку, ось результати (як тільки одна плитка):введіть тут опис зображення


0

Я прочитав більшість посилань і витратив деякий час, щоб придумати інше рішення. Я не знаю, добре це чи ні, але для імітації поведінки авто-плиток RPG Maker VX Ace (47 плиток) я почав робити щось подібне:

(зліва 0 або 1) + (право 0 або 1) + (вгору 0 або 1) + (вниз 0 або 1), тепер у мене є 5 випадків.

якщо розміщено 4 = Плитка 46

якщо 3 бордери =

якщо 2 4 випадки + 2 випадки не впевнені в алгоритмі, але не так багато гілок зробити.

якщо 1 = працює над цим, але кожен напрямок може закінчитися в 4 випадках

якщо 0 = я можу використовувати алгоритм чисел, показаний у посиланнях з 1, 2, 4, 8 та отримання ідентифікатора від 1 до 15, я можу безпосередньо використовувати.

Я не програміст і не найкращий з математичними алгоритмами, і рішення 1, 2, 4, 8, 16, 32, 64, 128 мені теж не сподобалось.

Можливо, мій підхід принаймні кращий за це.


1
Я не впевнений, що ця відповідь повністю відповідає на питання, чи могли б ви пояснити трохи більше? Якщо ви посилаєтесь на щось інше, чи могли б ви хоча б посилання на нього?
Vaillancourt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.