Pohyby a reprezentace těles


Všechna tělesa jsou v rovině.
K určení polohy používáme souřadnicový systém [x,y], kde obě souřadnice jsou zapsány ve formátu long long ( 64bit signed integer ) .
Každá jednotka souřadnic reprezentuje 1km , takže touto sítí pokrýváme necelé 4 miliony světelných let čtverečních ( 2x2 ) , do kterých se ( s přehledem ) vejde galaxie ( kdybychom ale zvolili jako základní jednotku metr místo kilometru , už se nevejde ) .
Bod [0,0] označuje střed galaxie ( tam je černá díra , což teď není podstatné ) .

Hvězdy jsou statické .
Planety a měsíce obíhají ( v této reprezentaci je to jen o málo těžší , než kdyby stály ) .

Loď se v jednu chvíli vyskytuje právě v jedné oblasti :
1/ volný prostor
2/ sluneční soustava
3/ gravitační pole planety
4/ gravitační pole měsíce

Ve volném prostoru může loď vykonávat následující akce :
1/ Stát na místě , což nic nestojí ( krom energie na provoz systémů ) , může mít vypnuté motory a nic nedělat , žádné síly na ni nepůsobí .
2/ Pohybovat se rovnoměrně přímočaře . K tomu také loď nic nepotřebuje ( jako v bodu 1/ )  . Vypočítat nové souřadnice lodi je jednoduché , máme daný směr , takže stačí vzdálenost , která je v * t ( rychlost je známá také předem , čas víme z předchozího updatu ) .
3/ Pohybovat se zrychleně přímočaře , pokud má zapnuté motory . V tom případě lze zrychlení spočítat podle vzorce a = F / m . F je síla , která odpovídá tahu motoru ( tam je v tera newtonech ) , m je hmotnost lodi a jejího nákladu ( tu umí lodě vracet funkcí ) . Během letu se hmotnost mění ( snižuje spotřebou paliva ) , výsledné zrychlení lze aproximovat průměrnou hmotností ( tu známe , protože vždy řešíme pohyb za čas a známe spotřebu za čas ) . Zrychlení může být i záporné , když loď zpomaluje . Žádné další síly na loď nepůsobí , takže se nová pozice lodi spočítá rychle ( známe starou pozici a směr , umíme spočítat dráhu , kterou urazí za čas pomocí zrychlení vzorcem s = v0 * t + (a * t * t) / 2 , kde v0 je rychlost , kterou loď měla na začátku ( při minulém updatu ) , a je zrychlení ( podle vzorečku ze síly a hmotnosti ) a t je čas ( ten známe od posledního updatu ) .
4/ Zatáčet , tedy měnit směr . Tady budeme aproximovat , protože k reálné simulaci by bylo třeba počítat ještě s ,, délkou zatáčky ´´ ( resp. jejím poloměrem ) . Proto zavádím aproximaci , ve které platí , že jakákoliv změna kurzu lze provést v nulovém čase a stojí pouze palivo . Kolik paliva stojí změna kurzu , lze zjistit následujícím způsobem ( to nemá žádný fyzikální podklad , to jsem prostě jen tak vycucal z prstů ) : Otočení o 180 stupňů při rychlosti v stojí tolik paliva , kolik by stálo dosažení rychlosti v s aktuálními lodními motory ( tedy m * v * spotřeba / F , kde m je hmotnost lodi , v je rychlost , ve které se dělá manévr , spotřeba je spotřeba motoru za vteřinu a F je výkon motoru - tento vztah je odvozen z normálních fyzikálních vzorců posbíraných na wikipedii ) . Otočení o méně než 180 stupňů stojí paliva méně ( lineárně méně ) .

V sluneční soustavě může loď vykonávat následující akce :
1/ Stát na místě , což stojí palivo . Motory musí překonávat sílu , která se rovná M * m * kapa / r * r , kde M je hmotnost hvězdy , m je hmotnost lodi , kapa je 6.67 / 10^11 , r je vzdálenost lodi od hvězdy . Sílu , kterou musí loď překonávat , označme F . Tah motorů označme T . Spotřebu paliva pro stání na místě lze spočítat jako F / T * spotřeba motoru . Pokud je F / T větší než 1 , nespadá to do tohoto bodu , ale těleso padá do hvězdy ( pravidla pro tuto situaci budou popsána dále ) . NEJBLIŽŠÍ ORBITA , PO KTERÉ LZE OBÍHAT , JE DVOJNÁSOBEK POLOMĚRU .
2/ Obíhat na orbitě kolem hvězdy po kružnici ,, správnou ´´ rychlostí . Ta může být určena buď rychlostí , nebo vzdáleností od středu hvězdy , vztah pro to je v = sqrt(kapa * M / r) , kde v je rychlost , kapa je jako minule 6.67 / 10^11 , M je hmotnost hvězdy , r je vzdálenost obíhání ( naopak je ten vzorec r = v * v / (kapa * M) - kapu a M známe pořád , u v nebo r známe jedno z toho ) .
3/ Obíhat na orbitě kolem hvězdy po kružnici a zrychlovat na ,, správnou ´´ rychlost . Při této činnosti je třeba překonávat sílu , kterou je loď přitahována ke Slunci ( ve skutečnosti ji není nutné překonávat pořád celou , ale budeme předpokládat , že ano ) . Jak tuto sílu vypočítat , je napsáno v bodě 1/ , ta síla je tatáž , označme jako F1 . F1 působí kolmo na tah motoru , který označíme T . Pro další výpočty je tedy třeba T upravit o F1 . Výslednou sílu označíme Tdef . Tdef = sqrt(T * T - F1 * F1) . Novou polohu pro pohyb po kružnici pak počítáme pomocí Tdef a jinak úplně stejně jako vzdálenost při zrychleném přímočarém pohybu ( tj. s = v0 * t + (t * t * F / m) / 2) , jen je to po kružnici .
4/ Pohybovat se zrychleně přímočaře . Tady platí totéž , co pro zrychlený přímočarý pohyb ve volném prostoru , ale je vždy třeba počítat s gravitační silou hvězdy . Tady opět používáme aproximaci ( místo derivací ) . Před reálným přemístěním lodi se pohyb spočte tak , jako kdyby se jednalo o pohyb ve volném prostoru . Pak se spočte střední bod té dráhy a z něj se spočítá vektor směrem k hvězdě . Velikost tohoto vektoru se rovná gravitační síle , která působí na loď od hvězdy ( ta síla je spočítaná v bodě 1/ ) . Síla motoru se musí tímto vektorem přenásobit . Abychom zjistili skutečnou sílu , kterou loď zrychluje ( jako ta Tdef v minulém bodě ) , musíme započítat gravitaci . Pokud gravitační vektor označíme F1 a sílu motoru T , zjistíme Tdef tak , že vektor o velikosti T nasměrujeme tak , aby výsledný vektor Tdef ( který vznikne složením F1 a T ) ukazoval směrem , kterým chce loď letět . Složením vektorů pak určíme velikost Tdef , kterou použijeme ke zrychlení . Z toho vyplývá , že Tdef může být větší i menší než T , podle toho , kterým směrem míří ( a odpovídá to tomu , že pokud letí loď ke hvězdě , její gravitace jí pomáhá ) .
5/ Pád . Loď stojí na místě ( nějakým způsobem se tam dostala , třeba vyskočila z podprostoru , nebo jí došlo palivo v bodě 1/ ) a nemá puštěné motory . V takovém případě začne padat směrem ke hvězdě . Teoreticky je to speciální případ bodu 4/ , prakticky tady existuje velmi jednoduchý vzoreček , takže nemusíme aproximovat . Používáme tedy normálně vzorec pro volný pád ve vakuu : s = v0 * t + a * t * t / 2 , kde v0 je počáteční rychlost ( úplně na počátku je sice nulová , ale poloha se v průběhu pádu updatuje ) , t je čas , a je gravitační zrychlení . Jediná potíž je , že gravitační zrychlení se mění se vzdáleností , ale zatím použijeme konstantní ( kapa * M / (r * r) , kde kapa je stále 6.67 / 10^11 , M je hmotnost hvězdy a r je její poloměr . Dopadne-li loď na povrch , je zničena . Tomu může zabránit tak , že v průběhu pádu začne vykonávat nějakou jinou činnost , kterou v tu chvíli vykonávat může ( typicky odletět pryč ) .
6/ Zatáčet , což probíhá stejně jako bod 4/ pohybu ve volném prostoru .
7/ Zpomalit při vstupu na orbitu . Tato situace nastává v případě , že loď má vyšší rychlost , než orbita , na které chce obíhat . V takovém případě proběhne zpomalení okamžitě a stojí tolik paliva , kolik by to stálo , kdyby to trvalo nějaký čas ( spočte se to přes výkon a spotřebu motorů , úplně stejně jako při otáčení v bodu 4/ pohybu ve volném prostoru ) .
ČASEM SE BUDE ZPOMALOVÁNÍ ŘEŠIT NĚJAK ROZUMNĚ A OTÁČENÍ MOŽNÁ TAKY , ALE SPÍŠ TO ZPOMALOVÁNÍ !! V KAŽÉDM PŘÍPADĚ VŠECHNY AKCE , KTERÉ PROBĚHNOU ,, V NULOVÉM ČASE ´´ A STOJÍ NĚJAKÉ PALIVO ,, JAKO KDYBY V ČASE PROBĚHLY ´´ , SE BUDOU PŘEDĚLÁVAT .... upozorňuji na to proto , aby tomu bylo přizpůsobeno psaní kódu , aby to tam nebylo nějak moc zadrátované .

V gravitačním poli planety a měsíce jsou povoleny stejné akce jako pro sluneční soustavu , jen se místo hvězdy používá planeta či měsíc .

Základní vymezení oblastí ( postupně podle priorit ) :
1/ Kolem každého měsíce je gravitační pole měsíce , což je kruh o poloměru M / 10^16 ( M je hmotnost v kilogramech , poloměr vyjde v metrech ) .
2/ Kolem každé planety je gravitační pole planety , což je kruh o poloměru M / 10^16 ( M je hmotnost v kilogramech , poloměr vyjde v metrech ) .
3/ Kolem každé hvězdy je sluneční soustava , což je kruh o poloměru M / 10^16 ( M je hmotnost v kilogramech , poloměr vyjde v metrech ) .
!!!! TO , ŽE SE LOĎ MÍSTNĚ VYSKYTUJE V NĚJAKÉ OBLASTI , JEŠTĚ NEZNAMENÁ , ŽE V NÍ SKUTEČNĚ JE !!!!

Přechody mezi oblastmi :
Vletí-li loď do nějaké oblasti ( nebo oblast do lodi ) , jsou dvě možnosti :
1/ Loď do oblasti vstoupí , pokud buďto hráč chtěl ( pak nezávisí na rychlosti ) , nebo proto , že musí ( protože loď letěla moc pomalu ) .
2/ Loď oblastí proletí ( pokud hráč nechtěl a loď letěla dostatečně rychle ) .
Ta ,, hraniční rychlost ´´ ( která rozhoduje o tom , jestli loď vstoupí do oblasti ) se mění v závislosti na poloze lodi . Zjednodušeně řečeno platí , že aby se loď do oblasti nedostala , musí mít vyšší rychlost , než takovou , aby v daném místě obíhala po kružnici . Rychlost tedy musí být tím větší , čím blíž je loď ke středu oblasti .  V momentě , kdy se vyskytuje v bodě , kde by mohla obíhat po kružnici , do oblasti automaticky vstupí a začne tam obíhat . Z tohoto pravidla existuje výjimka : je-li loď ke středu tělesa ( hvězdy , planety , měsíce ) blíž než 2x poloměr ( to je nejnižší orbita ) , přestoupí na tuto orbitu vynuceně , jako kdyby hráč do oblasti ,, chtěl ´´ vletět ( proběhne vstup lodi do oblasti , viz níže ) .
ZDE JE NUTNO SPOČÍTAT , JESTLI A KDE LOĎ DO OBLASTI VSTOUPÍ A NASTAVIT EVENT UŽ VE CHVÍLI , KDY DO OBLASTI VSTUPUJE ( případně už když nastavuje kurz , což ale není moc složité , protože vzhledem k tomu , kde loď je , bude stačit projít několik málo hypoteticky možných oblastí , které stejně vzhledem k ,, řídkosti ´´ vesmíru většinou nebudou v cestě ) .

Vstup lodi do oblasti :
Mohou nastat v zásadě tři možnosti :
1/ Rychlost lodi je přesně adekvátní tomu , kde do oblasti vstupuje ( to bývá typicky ten ,, nedobrovolný vstup ´´ ) . V takovém případě bude obíhat po kružnici ( viz. akce ve sluneční soustavě , bod 2/ ) . Případná úprava kurzu lodi je provedena automaticky , nestojí ani žádné palivo .
2/ Rychlost lodi je vyšší , než by bylo adekvátní oběhu ( to bývá typicky případ , kdy hráč do soustavy chce vstoupit , nebo už se dostane tak blízko , že nemá jinou možnost ) . V tomto případě se loď sice automaticky převede do nového kurzu ( po kružnici ) , což žádné palivo nestojí , ale je třeba upravit rychlost . Úprava rychlosti stojí palivo a to stejně , jako kdyby měla tu rychlost upravovat normálně , jen v tomto případě proběhne zpomalení v nulovém čase . Cena paliva se spočítá stejně jako v bodu 4/ pohybu ve volném prostoru . Nemá-li loď dostatek paliva , buďto se zřítí a je zničena ( pokud se jednalo o ,, nedoborovlný vstup ´´ , kdy se loď ocitla ve vzdálenosti 2x poloměr od toho středu , viz. přechody mezi oblastmi ) , nebo prostě do oblasti nevstoupí ( to znamená , že je dál než 2x poloměr od středu , pokud je blíž než 2x poloměr od středu a zároveň nemá dost paliva na zbrždění , dojde ke kolizi ) .
3/ Rychlost lodi je nižší , než by bylo adekvátní oběhu ( to bývá případ nedobrovolného vstupu do oblasti hned na začátku ) . V tomto případě se loď zastaví na kraji oblasti a začne padat volným pádem ( viz. bod 5/ akcí ve sluneční soustavě ) .

Výstup lodi z oblasti :
Loď z oblasti vystoupí jen a pouze tak , že doletí za její hranici ( jinak vystoupit nelze ) .

Přistávání :
Přistávat se dá lodí na planětě či měsíci pouze v případě , že hráč má na dotyčné planětě či měsíci základnu . 
Přistávací manévr začíná na nejnižší orbitě planety ( 2x poloměr ) s podmínkou , že maximální rychlost lodi je v té chvíli taková , jako kdyby loď na té nejbližší orbitě obíhala ( s vyšší rychlostí nelze přistávat ) .
Jsou-li splněny podmínky , trvá přistání nějaké množství času ( závislé na hmotnosti lodi a planety a na síle motoru - na tohle napíšu funkci , to nebude těžké ) , po které musí mít loď plně zažehnuté motory ( z toho vyplývá spotřeba paliva ) .

Pronásledování lodí :
Vyřešil jsem prakticky všechny problémy nějakou ,, rozumnou aproximací ´´ , která dělá rozumný poměr mezi spotřebovaným palivem a dobou pronásledování . Každopádně je výsledek zejména skvělý v tom , že se to bude snadno programovat .
Pronásledování vypadá různě v závislosti na tom , co dělá cíl :
1/ Stojí na místě . V tom případě pronásledovatel prostě nastaví kurz k němu ( o tom bude ještě více dále ) .
2/ Obíhá po kružnici . V tom případě pronásledovatel doletí na tu kružnici ( jako kdyby tam chtěl obíhat sám ) a vydá se nějakým směrem ( ten směr bude záviset na tom , jak cíl chytí rychleji , což jde velmi snadno zjistit - napřed se spočítá , za jak dlouho cíl dostihne ,, v protisměru ´´ a pak se zjistí , jestli ho nechytí ,, po směru ´´ dřív - respektive prostě jestli tu loď ,, po směru ´´ za ten čas předběhne ) .
3/ Letí po přímce :
3a/ Kdyby stál pronásledovatel na místě , cíl by se k němu svým pohybem přibližoval . V tomto případě doleží pronásledovatel k přímce po kolmici a následně se vydá po přímce za cílem .
3b/ Kdyby stál pronásledovatel na místě , cíl by se od něj vzdaloval . V tomto případě letí pronásledovatel na místo , kde je cíl ( jako v bodě 1/ ) a pak se za ním vydá po přímce .
Při nastavení kurzu přímo někam , které se využívá vlastně ve všech bodech 1/ až 3/ ( v prvním explicitně , v dalších implicitně ) , se může stát , že loď cestou potká nějakou oblast . V takovém případě je nastaveno , že do té oblasti nechce vstoupit ( viz. vstup do oblasti ) . Vstoupí-li i přesto do dané oblasti , může ji ,, obletět ´´ ( ne celou ) po části kružnice a pokračovat dál tak , jak začal ( tedy do oblasti vstoupí po přímce , pak oběhne kousek po kružnici a nakonec ji zas opustí po přímce , která je shodná s tou , po které do oblasti vsotupil ) .
Změní-li pronásledovaný své chování , celá akce Pronásledování lodí proběhne znova ( jako kdyby bylo zadáno nové pronásledování ) .

Násobné pronásledování :
Je-li loď A pronásledována lodí B , loď B se pohybuje buď po přímce , nebo po kružnici . Na oba typy máme definované pronásledování . Loď C tedy může pronásledovat loď B .
Problém nastane v momentě , kdy se lodě pronásledují cyklicky . V momentě , kdy se cyklus uzavře , je detekován ( což je snadné ) . Poté , co je cyklus detekován , zvolí se bod , který je pro všechny lodě co nejlépe dostupný ( udělá se prostě půměr z x-ových a y-ových souřadnic všech lodí ) . Mohou nastat následující případy :
1/ Bod je ve volném prostoru . V tom případě prostě doletí všechny lodě  na to místo .
2/ Bod je v nějaké oblasti :
2a/ Je gravitačnímu středu blíž než 2 x poloměr . V takovém případě se zvolí bod , který je od gravitačního středu vzdálen přesně 2 x poloměr a zároveň je k původnímu bodu nejblíže a přejde se k bodu 2b/ .
2b/ Je od gravitačního středu dále než 2 x poloměr . V takovém případě je zvolena orbita , na které tento bod leží . Lodě se pak setkávají na orbitě tak , že loď , která na orbitu dorazí první , bude jakkoliv obíhat a všechny ostatní budou pak pronásledovat ji ( poté , co na orbitu dorazí ) .

Chce-li se hráč přemístit na nějakou planetu , řeší se situace tak , že vlastně planetu pronásleduje , jako kdyby to byla loď .

ČASEM BUDE MNOHO Z TĚCH AKCÍ PROBÍHAT ,, AUTOMATICKY ´´ . ČÍM DÁL , TÍM VYŠŠÍ ( OBECNĚJŠÍ ) CÍLE BUDE UŽIVATEL MOCI ZADÁVAT . Je proto dobré probramovat co nejvíce atomicky .
VŠEMOŽNÉ KOLIZNÍ KURZY ( a nejen to ) BUDOU VYVOLÁVAT VAROVÁNÍ PRO HRÁČE !! To znamená , že prakticky každá z funkcí musí mít dvě verze - první , která výsledek jen spočítá a druhou , která jej pak i provede . Žádná funkce , která něco skutečně vykonává ( nastavuje kurz , posouvá lodí , cokoliv přepočítává ) , by neměla VŮBEC NIC počítat ( protože ty funkce na počítání budou třeba pro hlášky uživatelům ) .

Celá simulace je realizována tak , aby nezatěžovala procesor . Je tedy vždy uložen pouze čas a stav ( u každého objektu zvlášť ) , příčemž do stavu patří informace jako směr , aktuální činnost ( zrychlování , zpomalování , .... ) . Existuje metoda , která situaci aktualizuje ( tedy přepočítá stav , ten uloží a k němu uloží aktuální čas přepočítání ) . Před každou akcí , kterou je třeba udělat , se zavolá aktualizace .
Problém nastává v momentě , kdy lodě interreagují mezi sebou a loď , která interakci vyvolá , netuší , s kým vlastně .
Takových situací moc nenastává , ale některé přece , například při použití senzorů . Tady využijeme toho , že pokud zdrojová loď neví , která loď je přímo cílem , musí znát místo .
V podobných případech ( jako například použití senzorů ) je řešení takové , že lodě rozdělíme na sektory ( sektorem můžeme pro zjednodušení označit oblast , avšak v tomto případě je nutné procházet i podoblasti - například použití senzorů na sluneční soustavu musí vyhledat i lodě , které obíhají planety a měsíce ) . Protože jsou sektory pevně dané , můžeme snadno zjistit jejich opuštění ( na to nastavíme event , který přesune loď do jiného sektoru , respektive přesun ověří ) . Při použití senzorů ( či jiných plošných akcích ) pak prohledáváme sektory a testujeme lodě , které v sektorech najdeme .

K fungování senzorů ( aby nezatěžovaly procesor ) :
Hráč zaměří bod ( to v případě dálkových senzorů , blízké jsou zaměřeny automaticky se středem v jeho lodi ) . Systém mu vrátí pouze SEZNAM lodí ( nikoliv jejich polohy , takže nebude nutné při každém použití senzorů polohy přepočítávat ) .
Hráči si bude moci vybrat cca 2 lodi , které chce zobrazit a sledovat ( pokud bude chtít sledovat jiné , musí zrušit sledování těch předchozích ) . 
Psané kódu senzorů nepatří obecně k psaní těch poloh , je to zde uvedeno proto , aby bylo jasno , jak budou fungovat .

!!!!!!!! POZOR NA JEDNOTKY !!!!!!!! 
Při počítání čehokoliv je nutné převádět na společné jednotky , většinou je to v tera-jednotkách , ale ne vždy .
POZOR , už jsem udělal nějaké chyby , je třeba u toho přemýšlet , konkrétně mě nachytal kilogram , který je základní jednotka , ačkoliv má už předponu ( takže když jsem chtěl převést kilogramy tak , abych mohl pracovat například v jednom vzorci s mega newtony , neodpovídají mega newtonům zrovna mega gramy , ale tera gramy , což člověka zmate ) .