Search the Community
Showing results for tags 'arma 3'.
-
Zdravíčko přátelé - možná jste někdy ve svém módu řešili animace, interpolaci, či jakýkoliv plynulý pohyb předmětu či čehokoliv jiného. Dá se samozřejmě přes lineární konverzi (jejíž algoritmus najdeme ve všech jazykových podobách na internetu) zařídit ostrý pohyb z bodu A do bodu B. Pokud ale chceme zajistit plynulejší pohyb s rozjezdem a dojezdem - tedy zrychlením a zpomalením, které nebije tolik do očí - je potřeba upravit chování naší lineární konverze tak, aby buď rovnou pracovala na algoritmu, který toto bere v potaz, případně můžeme toto nasimulovat pomocí nástrojů nám svěřených. Nejdříve si ukážeme "hack" verzi - tedy pro mě jako absolutního nematikáře - absolutní začátek a experiment celé pseudofunkce. Příklad si uvedeme ve hře Arma 3, pro pohyb kamery v cutscéně. Arma 3 nám nabízí funkce pro lineární pohyb kamery z bodu A do bodu B - ostrou cestou. Tím je myšleno, že po spuštění funkce se kamera fixní rychlostí přesune z jejího dosavadního bodu do bodu zadaný v parametru funkce v čase také zadaném v parametru funkce: _cam = "camera" camCreate [0,0,0]; //Vytvořit kameru na pozici [0,0,0] _cam cameraEffect ["internal","back"]; //Přepnout obraz hráče do této kamery _cam camPreparePos [10,10,10]; //připravit přesun na pozici [10,10,10] _cam camCommitPrepared 5; //přesun trvá 5s Vizuálně takový přesun je sice použitelný, nicméně není plynulý a strašně neuhlazený (hlavně při pohybu na více bodů v řadě). Double LERP Ukážeme si ten nejjednodušší způsob, který vymyslí hlavně nematikář - za pomocí lineárního pohybu, který arma nabízí, můžeme nasimulovat rozjezd a dojezd pomocí zdvojeného lerpování (linearní interpolace, kterou obstará příkaz camCommitPrepared). //Používáme globální proměnné pro zviditelnění kamer pro skript na EachFrame V_cam = "camera" camCreate [0,0,0]; //Vytvořit kameru na pozici [0,0,0] V_cam cameraEffect ["internal","back"]; //Přepnout obraz hráče do této kamery V_camPos = "camera" camCreate [0,0,0]; //Vytvoří kameru využitou na pozadí pro výpočet lineráního přesunu kamery V_camLerp = addMissionEventHandler ["EachFrame", //Vytvoříme unscheduled environment spuštěný na každém vykresleném snímku { _T_pos = getPosASL V_camPos; //Vezmeme si ASL pozici kamery pro přesun _C_pos = getPosASL V_cam; //Vezmeme si ASL pozici vizuální kamery _T_pos = vectorLinearConversion [0,1,0.1,_C_pos, _T_pos]; //Provedeme lineární konverzi (lerp) s progressem 0..0.1..1 (toto zajistí efekt akcelerace) V_cam camPreparePos (ASLToATL _T_pos); //Nastavíme výslednou (interpolovanou) pozici V_cam camCommitPrepared 0; }]; V_camPos camPreparePos [10,10,10]; //připravit přesun na pozici [10,10,10] V_camPos camCommitPrepared 5; //přesun trvá 5s sleep 5.1; //Počkáme 5s na přesun kamery + 0.1s na dokončení akcelerace naší vizuální kamery removeMissionEventHandler ["EachFrame", V_camLerp]; //Zničíme lerpovací skript Můžeme si samozřejmě napsat kompletní funkci, která využije příkaz vectorLinearConversion dvakrát a obejde tím rovnou vytvoření druhé kamery a příkaz camCommitPrepared pro přesouvací kameru. Pro jednoduchost a čitelnost skriptu (a variabilitu) jsem předal funkci takto Pro práci s pohybem kamery (resp. pro relevantní výpočty a manipulace) využívám výhradně pozici ve tvaru ASL (Above Sea Level), protože při interpolaci ATL (Above Terrain Level) kamera při přesunu skáče dle toho jestli pod sebou zrovna nemá kopeček, či díru (proto zjišťuji polohy ASL a poté překládám do ATL při nastavení pozice samotné kamery - příkaz pracuje s ATL pozicemi a sám interpoluje na ASL) Interpolace pomocí algoritmu Tou "správnou" cestou by měla být pravá matematická interpolace se zahrnutím easingu už v algoritmu. Existuje mnoho různých algoritmu na ty samé pohyby - ať už jde jen o zrychlení, jen o zpomalení, či oboje - na vše je několik variant. Ukážeme si jenom tu základní - na zbytek uvádím silný zdroj: http://gizma.com/easing/ _posA = [0,0,0]; //Nastavení bodů _posB = [10,10,10]; _startTime = time; //Nastavení výchozího času a délky průběhu _endTime = _startTime + 5; //+5s _eh = addMissionEventHandler ["EachFrame", { _progress = linearConversion [_startTime, _endTime, time, 0, 1, true]; //Převod průběhu času na range 0..1 s clamp _progress = _progress * _progress * (3 - 2 * _progress); //https://www.wolframalpha.com/input/?i=x+*+x+*+%283+-+2+*+x%29 (křivka pro easing-inout) _curPos = vectorLinearConversion [0,1,_progress, _posA, _posB]; //Vlastní výpočet bodu na trase (interpolace s easingem) }]; sleep 5; //Celý pohyb i s akcelerací bude probíhat přesně 5s removeMissionEventHandler ["EachFrame", _eh]; Kdo chce bejt absolutní fajnšmejkr, tak tu má ještě funkci pro lineární interpolaci (i když ji skoro každej engine i samotný jazyk nabízí už v nějaké matematické třídě) func_myLerp = { params ["_A", "_B", "_progress"]; //Parametry funkce _progress = _progress max 0 min 1; //Clamp na range 0..1 (_A + (_B - _A) * _progress); };