Podstata tycoon terénu je založená na úprave trojuholníkovej mriežky takým spôsobom, aby z každej strany bola každá strana tzv. nábežnou stranou, čo bolo bližšie vysvetlené v jednotlivých článkoch. Takýmto spôsobom je možné vykresliť tycoon terén, buď už v predspracovanom formáte, teda vtedy, ak sú súradnice terénu explicitne definované, alebo tak, že terén, súradnice terénu sú implicitne definované a explicitne dodefinované pri kliknutí myšou na príslušný vrchol, vertex. Problém je ten, že daný algoritmus neeviduje jednotlivé prevýšenia terénu.
Všeobecne hra Transport Tycoon a systematika ohľadne tycoon terrain by nebola plnohodnotná, ak by tam nefigurovalo prevýšenie terénu.
Na vyriešenie tohto problému ma napadlo prechádzať každý jeden vertex v teréne a kontrolovať, či dané prevýšenie v štyroch smeroch na seba kolmých je vyhovujúce. V prípade, ak nie, tak sa reviduje dané prevýšenie úpravou indexu na vyššie číslo, resp. nižšie, pri znižovaní terénu. Pretože terén je možné zvyšovať a znižovať. Najskôr ma napadlo riešenie s klasickou lineárnou algebrou v tom zmysle, že by sme kontrolovali uhol medzi jednotlivými prevýšeniami. Je zrejmé, že uhol medzi dvoma vertexmi, vrcholmi musí byť vždy rovnaký pre celý terén. Teda, medzi prevýšením 2 by bol uhol nejaký, ale všade v rámci celého terénu by bol uhol rovnaký. Pri prevýšení 3 by bol síce uhol strmší, ale stále rovnaký pri danom prevýšení v rámci celého terénu. Platné prevýšenie by bolo také, ktoré by bolo len maximálne do prevýšenia 2 a s tým spojená veľkosť uhla prevýšenia. Takže neexistovalo by v celom teréne prípustné prevýšenie 3 a viac, alebo -3 a menej, ale stále len 2 alebo resp. -2, aby to nebolo dané v absolútnej hodnote. Lenže vzápätí ma napadlo, že pri takejto kontrole by som musel definovať nejakú mapu, dodatočnú mapu, ktorá by definovala rôzne prevýšenia a k tomu prislúchajúce veľkosti uhlov. Ak som si takúto mapu nakreslil, tak som zistil, že nie je nutné kontrolovať a zisťovať uhol medzi vertexmi, vrcholmi, ale že už je možné priamo napísať akési indexy prevýšenia a upravovať tieto indexy podľa situácie.
Algoritmus funguje relatívne jednoducho. Vygeneruje sa mapa podľa hešovacej tabuľky taká, ktorá bude obsahovať jednotlivé prevýšenia terénu. Jedná sa o to, že terén obsahuje súradnice v desatinných číslach a jednotlivé indexy prevýšenia by mali figurovať v celých číslach. Nie je to nutné, ale je to výhodnejšie, pretože prevýšenie terénu je dané vždy ako celé číslo, teda v zmysle prevýšenia o +1, je prevýšenie 2, následne 3, atď. Takže nemá zmysel uvažovať hodnotu 2.0, 3.0, aj keď by to principiálne nebol problém a možno by sa nemusela mapa pregenerovávať len pre tento účel a bolo by možné zahrnúť priamo do kontrolujúcej podmienky už preddefinovanú hodnotu pre dané prevýšenie aj v desatinnom zobrazení. Ale človek, ak začína, tak ako teraz v mojom prípade, tak je výhodnejšie to naprogramovať možno trochu redundantne, ale mať istotu v tom, že to bude napísané správne, transparentne. Potom to určite budem ešte optimalizovať.
V ďalších krokoch sa bude kontrolovať každý vrchol, vertex mapy. Je to jednoduché prechádzanie stavového priestoru. Začne sa s nejakou súradnicou a ku každej súradnici sa implicitne kontroluje súradnica v štyroch smeroch, teda kvázi povedané "hore", "dole", "doľava" a "doprava". Rovnakým princípom ako pri ostatných algoritmoch, teda vykoná sa sčítanie a odčítanie pre x-voú a y-ovú súradnicu o +1/-1. Tento stav sa kontroluje pre dodatočnú mapu, ktorá bola predtým pregenerovaná na základe pôvodnej mapy a bola obohatená o jednotlivé indexy podľa hešovacej tabuľky. Takýmto spôsobom sa zisťujú jednotlivé prevýšenia terénu. Najskôr som to vyriešil tak, že jednotlivé index sa upravovali v satelitoch, teda v prináležiacich vrcholoch z hlavného vertexu. Teda, akonáhle sa vyskytla nejaká nezrovnalosť, teda prevýšenie bolo väčšie než 2, tak automaticky sa upravili všetky 4 indexy pre daný hlavný vertex. Toto bola chyba, ktorú som opravil hneď pri prvom testovaní. Problém bol v tom, že akonáhle vykonáte úpravu 4 satelitných indexov, tak sa stane to, že sa upraví aj index, ktorý bol kliknutý myšou, teda ten inkriminovaný index, ktorý bol navýšený/ponížený. Ak klikne používateľ na nejaký vrchol, tak kým daný algoritmus príde k danému kliknutému vrcholu, tak taný vrchol bude zmenený, teda povýšený a to je chyba, pretože kliknutý vrchol nemá byť zmenený, len jeho okolité vrcholy. Tu dochádza k určitej nezrovnalosti, dichotómii. Pretože moja pôvodná verzia bázického algoritmu funguje na princípe kliknutia vrcholu a jeho úpravy a nie tak, že algoritmus kontroluje všetky vrcholy. V tomto prípade to realizujem tak, že algoritmus kontroluje všetky vrcholy, pretože je ťažké zabezpečiť všetky jednotlivé prevýšenia terénu. Že, ak by ste klikli myšou na kopec s prevýšením 5, tak algoritmus by musel cyklicky upravovať všetky prevýšenia do úrovne 5. Takže síce by nemusel prechádzať celý terén, čo teda v optimalizovanej forme bude doprogramované, ale tak či tak by musel revidovať všetky úrovne a nebolo by zrejmé, ktorá úroveň v akom rozpoložení by mala figurovať. Takže z toho dôvodu sa kontroluje každý vrchol terénu. A ak to takto je, tak potom sa musí vykonať jednoduchá úprava algoritmu a to taká, že sa bude revidovať nie každý satelitný vertex, ale hlavný vertex na základe nespĺňajúcej podmienky niektorého satelitného vertexu. Takže, ak príde v limitnom prípade pri kliknutom vertexe a zistí sa prevýšenie 3, namiesto prevýšenia 2, tak sa upraví daný vertex a teda ten ktorý bol vedľa hlavného vertexu a nie samotný hlavný vertex, ktorý bol kliknutý myšou. A toto je veľmi dôležitá úprava algoritmu.
Potom systematika algoritmu bude generovať správne rozpoloženie terénu, ako je možné vidieť na obrázku.
Zdrojový kód už je v opravenom formáte, avšak nie v celkovom optimalizovanom formáte v tom zmysle, že algoritmus neeviduje zmenšenú oblasť, región, pre rýchlejší výpočet. Ale to už nie je taký veľký problém, pretože som to vyskúšal zadať explicitne a algoritmus fungoval správne.
(GIT: https://github.com/indicatrix-git/tycoon-terrain-enhanced/blob/main/TerrainCollapse.cs)
(GIT: https://github.com/indicatrix-git/tycoon-terrain-enhanced/blob/main/TerrainCollapse.cs)
public void TerrainCollapse(int iCoordClick)
{
bool repeatMapTraverse = true;
Vector3 coordClick = coordsI[iCoordClick];
while (repeatMapTraverse)
{
for (int i = 0, z = 10; z <= 30; z++)
{
for (int x = 10; x <= 30; x++, i++)
{
Vector3 mainVertex = coordsI[i];
if (!((mainVertex.x == 0 || mainVertex.x == 256) && (mainVertex.z == 0 || mainVertex.z == 256)))
{
float upX = mainVertex.x + 1;
float downX = mainVertex.x - 1;
float leftZ = mainVertex.z + 1;
float rightZ = mainVertex.z - 1;
Vector3 upVertex = new Vector3(upX, FunctionalVertexValueY(upX, mainVertex.z), mainVertex.z);
Vector3 downVertex = new Vector3(downX, FunctionalVertexValueY(downX, mainVertex.z), mainVertex.z);
Vector3 leftVertex = new Vector3(mainVertex.x, FunctionalVertexValueY(mainVertex.x, leftZ), leftZ);
Vector3 rightVertex = new Vector3(mainVertex.x, FunctionalVertexValueY(mainVertex.x, rightZ), rightZ);
float n1 = DeltaY(mainVertex, upVertex);
float n2 = DeltaY(mainVertex, downVertex);
float n3 = DeltaY(mainVertex, leftVertex);
float n4 = DeltaY(mainVertex, rightVertex);
if (n1 == 2 || n2 == 2 || n3 == 2 || n4 == 2)
{
if(coordClick == mainVertex)
{
coordsI[i].y = coordsI[i].y;
}
else
{
coordsI[i].y = coordsI[i].y + 1;
}
repeatMapTraverse = true;
}
else repeatMapTraverse = false;
}
}
}
}
}
V nasledujúcom videu to popisujem podrobnejšie:



