FIT ČVUT

Adam Vesecký

NI-APH
Přednáška 6

Herní prostor

Nahodilost

Nahodilost ve hrách

Nahodilost je jeden z nejkritičtějších faktorů v gameplayi. Náhodné události poskytují hráčům jistou míru nejistoty, nutíce je k analyzování možných dopadů jejich kroků.

Náhodné generátory

LCRNG

  • Linear Congruential Random Number Generator
  • x_n = (ax_{n-1} + c) \mod{m}
  • začíná seedem
  • funguje dobře s prvočísly
  • pokud je dobře nakonfigurován, začne se cyklit až poté, co téměř vyčerpá celou doménu
  • používá jej rand() ze standardní C knihovny

Zpožděné Fibonacciho metody

  • x_n = (x_{n-j}\circ x_{n-k}) \mod{m}
  • díváme se do předchozí sekvence hodnot

Carry metody

  • přenese část výsledku z předchozí fáze do méně významných bitů další fáze
  • x_n = (x_{n-k}+x_{n-r} + c_{n-1}) \mod{m}

Náhodné generátory

Mersenne Twister

  • obří perioda 2^19937-1
  • splňuje Diehard test
  • používá SIMD instrukce

Mother of all

  • používá techniku násobení s přenosem
  • rychlejší než twister, perioda 2^250

Xoroshiro128+

  • vylepšený MOA, je rychlejší ale ne tak kvalitní
  • používán v Math.random() v browserech

PCG Family

  • jednoduché a nenáročné algoritmy

Distribuce náhodných funkcí

Doom

Transport Tycoon

Lehmer RNG

Gaussian MOA

Xorshift

Distribuce náhodných funkcí

Uniformní rozdělení

  • nejběžnější
  • použití: šum, náhodné řazení, hod kostkou

Gaussovo (normální rozdělení)

  • používá se u veličin, který mají nějaký průměr, od kterého se chceme odchýlit
  • dá se vypočítat s použitím uniformního generátoru (algoritmus Box-Muller)
  • použití: výška stromů, rozptyl při střelbě, rychlost, damage

Uniformní rozdělení

Gaussovo rozdělení

Pojmy

Seed

  • číslo, které inicializuje generátory náhodných čísel
  • pro větší nahodilost se může smíchat s uživatelským vstupem nebo časem

Loot

  • předměty, které hráč získá během gameplaye (virtuální peníze, nástroje, lektvary,...)

Spinning

  • volání generátoru náhodných čísel každý frame bez použití jeho výsledku ve hře
  • činí hru méně předvídatelnou

Rarity Slotting

  • kategorizace předmětů v RPG hrách (common, rare, epic, legendary)
  • používá se vážený součet přes rarity tabulku

Random encounter

  • populární mechanika RPG her
  • hráč potká enemáka a hra se přepne do battle módu
  • jakmile boj skončí, hráč dostane odměnu (zkušenosti, loot)

Nahodilost ve hrách

Final Fantasy 1 (1987)

  • předgenerovaná čísla čtená sekvenčně (256 hodnot v ROM)
  • objevovaly se stejné skupiny nepřátel - surprise determination

Super Mario 64 (1996)

  • používal LCRNG s 65114 možnými stavy
  • nepoužíval spinning

Pokémon (2002+)

  • od roku 2002 (Game Boy Advance) se spinningem

Darkwing Duck

  • loot závisel na dělitelnosti čísla framu

Nahodilost ve hrách

Pitfall! (1982)

  • používal posuvný registr
  • každá obrazovka byla definována 1 bajtem - celkem 256
  • např. pokud byl jistý bit 1, scéna obsahovala příkop

Doom (1993)

  • to nejhorší, co se nepovedlo - generátor náhodných čísel
  • statická tabulka 256 čísel čtená sekvenčně

XCOM: Enemy Unknown (2012)

  • bez spinningu - nebezpečné, když hráč udělal quick save v kritickém okamžiku

No Man's Sky (2016+)

  • všechny objekty jsou vytvořeny deterministickými algoritmy na základě 64-bitového seedu

Příklad: Doom (1993)

1 unsigned char rndtable[256] = {
2 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 ,
3 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 ,
4 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 ,
5 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 ,
6 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 ,
7 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 ,
8 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 ,
9 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 ,
10 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 ,
11 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 ,
12 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 ,
13 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 ,
14 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 ,
15 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 ,
16 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 ,
17 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 ,
18 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 ,
19 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 ,
20 120, 163, 236, 249
21 };
22
23 int P_Random (void) {
24 prndindex = (prndindex+1)&0xff;
25 return rndtable[prndindex];
26 }

Procedurální generování

Generování obsahu

  • nekonečný počet možností a možných struktur
  • šetří paměť, kterou by zabrala statická data
  • vysoká míra variability pro hráče
  • horší testování
  • můžeme vygenerovat nehratelný svět

Hry s procedurálním obsahem

  • Rogue (1980) - dungeony
  • Diablo (1996) - dungeony
  • OpenTTD (2004) - terén
  • Dwarf Fortress (2006) - content, historie, bytosti
  • Spore (2008) - bytosti, civilizace, planety
  • No Man's Sky (2016) - galaxie, planety, fauna, flóra

Generování pomocí AI

  • zatím spíše doménou generování statických assetů

Procedurální generátory

Generátor terénu

  • generátory šumu
  • box linear filter (box blur)
  • midpoint displacement

Generátor levelů

  • cyklické generátory
  • pochodující čtverce
  • generátory postavené na systému pravidel

Generátor patternů

  • generátory šumu
  • L-systémy
  • markovské řetězce

Zaplnění prostoru

  • náhodná procházka
  • buněčný automat
  • Poisson-disc sampling
  • settling
  • wang tiles

Rozdělování prostoru

  • binary space partition
  • voronoiské diagramy
  • dijkstrovy mapy
  • tree mapping

Příklad: generátor terénu

  1. vygeneruje se výšková mapa
  2. provede se upscale
  3. provede se interpolace
  4. aplikují se efekty (eroze, dilatace,...)

Příklad: generátor 2D levelu

  1. vytvoří se bounding box
  2. rozdělí se do regionů (axis-aligned binary splits)
  3. části se propojí
  4. každému regionu se přiřadí typ
  5. výsledek se vyhladí

Příklad: Settling

  1. vygenerují se obdélníky, které se překrývají
  2. aplikuje se odpudivá síla, dokud se nepřestanou překrývat
  3. vygenerují se místnosti
  4. vygenerují se cesty

Šum

  • Nahodilost se používá pro variaci hodnot, šum se používá pro variaci v čase či prostoru
  • Šumové funkce
    • Mřížkové
      • Perlinův šum, Simplex, Wavelet, Value
    • Bodové
      • Worleyho šum (Voronoiský/Buněčný)

Perlinův šum

Simplex

Worleyho šum

Perlinův šum

  • Perlinův šum - vytvořen Kenem Perlinem v roce 1983
  • Simplex - vylepšený Perlinův šum s méně artefakty
  • oba šumy používají pseudonáhodnou mřížku a interpolaci
  • šum se konstruuje z oktáv (amplituda signálu v daném měřítku)
  • signál je interpolován pomocí funkce 6t^2-15t^4+10t^3
1 float PerlinNoise2D(int x, int y, float persistence, int octaves, float zoom) {
2 float total = 0.0f;
3 // initial frequency and amplitude
4 float frequency = zoom;
5 float amplitude = 1.0f;
6
7 for (int i = 0; i < octaves; i++) {
8 // calculate noise
9 total = total + InterpolatedNoise(x*frequency, y*frequency) * amplitude;
10 // update frequency and amplitude
11 frequency = frequency * 2;
12 amplitude = amplitude * persistence;
13 }
14 return total;
15 }

Fraktály

  • objeveny v roce 1975
  • geometrické tvary, které je možno rozdělit na části, které jsou kopií celku
  • používá se pro generování textur a efektů
  • jejich využití v real-time je stále ve výzkumu

Geometrické hashování

Herní svět

  • průměr známého vesmíru: 10^{26} m
  • nejmenší teoretická struktura: 10^{-35} m
  • 256 bitů nám dá 10^{76}  hodnot
  • IEEE 754 formát ukládá 24b do mantisy: rozsah 1.67\cdot 10^7
    • single precision, 32bit: [\pm 2^{-126}, (2-2^{-23})\cdot 2^{127}]
    • double precision, 64bit: [\pm 2^{-1022}, (2-2^{-52})\cdot 2^{1023}]
  • obvykle se stanovuje metr jako základní jednotka, díky čemuž je nejmenší jednotka milimetr
  • rozsah pro 32b čísla:
RozměrNejmenší jednotkaHorní rozsah [m]Plocha
100mVesmírná loď1.67 x 10^9Průměr Slunce
1mAuto1.67 x 10^7Asie
1cmMince1.67 x 10^6Mexiko
1mmSmetí1.67 x 10^5Paříž
100μmPrach1.67 x 10^4Manhattan

Herní mapy

Přesnost IEEE 754

  • čtvrtina všech 32b čísel je v rozsahu [0,1] , polovina jich je v [-1,1]
  • od 8 388 608 do 16 777 216, přesnost pro 32b je 1
  • pokud je herní svět příliš velký, přesnost poblíž hranic herní mapy nebude dostatečná

Spatial partitioning

Bounding volume (obalující objem)

  • seskupuje objekty či jejich části dle jejich pozic a velikostí
  • pokud se objekt pohne, pohne se celá hierarchie
  • používá se ve fyzice a detekci kolizí

Spatial structure

  • struktura, která ukládá objekty dle jejich pozic
  • nepohybuje se, je statická v rámci herní mapy
  • používá se pro vyhledávání a preprocessing pro detekci kolizí
  • čím více objektů, tím více výhod

Implementace

  • Quad-tree - pro 2D a plochý 3D svět
  • Oct-tree - pro 3D
  • Grid - pro 2D
  • BSP (binary-space partitioning), portály, anti-portály,...

Oct-tree (oktanový strom)

Quad-tree

  • hierarchická struktura
  • každý vnitřní uzel má 4 potomky
  • přečnívající objekty se vkládají do všech potomků, kde mají průnik
  • pouze objekty v jednom listu mohou být v kolizi
  • užitečné pro outdoor prostředí
  • vhodné pro pomalu se pohybující objekty na 2D mapě

Quad-tree a geometrické hashování

Oct-tree

  • nepotřebuje žádný preprocessing
  • umožňuje komplexní geometrii levelu a jednoduchou editaci
  • strom může obsahovat jak celou scénu, tak jen jeden komplexní objekt
  • používá se pro LoD, detekci kolizí a voxelovou grafiku,...
  • bez dělení - 1 uzel
  • 1 dělení - 9 uzlů
  • 2 plná dělení - 73 uzlů
  • 3 plná dělení - 585 uzlů

Grid

  • implementuje se jako 1D/2D/3D pole
  • každá buňka obsahuje seznam entit uvnitř
  • pokud se entita dostane za hranu buňky, je potřeba ji přesunout
  • vhodné pro velké množství objektů, co se rychle pohybují
  • velmi rychlá lokalizace objektu (na rozdíl od quad-tree)
  • větší nároky na paměť, granularita je pevná

Navigace

Navigace

  • esenciální struktura pro mnoho her

Typy

  • lokální navigace na herní mapě (collision avoidance, ORCA)
  • globální navigace na herní mapě (pathfinding)
  • navigace v grafu (např. task-based planning)

Navigační graf

  • abstrahovaná reprezentace všech lokací ve hře, po kterých se dá chodit
  • obvykle obsahuje dodatečné atributy (snadnost chůze, priorita,...)
  • waypoint-based, mesh-based, grid-based
  • Uzel - pozice klíčové oblasti ve hře
  • Hrana - spojení mezi těmito oblastmi

Navigační graf

Waypoint-based

  • designér sám navrhne waypointy

Mesh-based (Navmesh)

  • vytváří se z polygonální reprezentace podlahy

Příklad: Unity mesh editor

Příklad: Counter-strike mesh editor

Navigační graf

Grid-based

  • vytváří se převedením herního prostředí do mřížky
  • traversability flag indikuje, zda je možno na buňku vkročit
  • geometrie sousednosti: tile, octile, hex
  • pokud se např. změní průchodnost buňky, stačí překlopit traversability flag

Příklad: Connection geometry

Pokémon pro GBA (Tile)

OpenTTD (Octile)

Heroes of M&M 3 (Hex)

Kombinovaná geometrie

  • jednotky se pohybují libovolně, ale statické objekty se nachází na mřížce

Starcraft II

Stardew Valley

Pathfinding

Aspekty

  • kompletnost - zda je nalezeno řešení či nikoliv
  • optimalita - kvalita řešení
  • hladkost - zda se herní objekt může pohybovat podél cesty hladce

Typ prostředí

  • statické - mapa se během gameplaye nezmění
  • dynamické - můžou se např. přidávat překážky, zablokovat cesta,...

NPC pohyb

  1. nalezni uzel, který je nejblíž pozici NPCčka: A
  2. nalezni uzel, který je nejblíž cílové pozici NPCčka: B
  3. najdi cestu z A do B
  4. jdi do A
  5. jdi do B s využitím pathfindingu
  6. jdi z B do cílové pozice

Pathfinding algoritmy

Uniformní vyhledávání

  • ignoruje cenu za překročení hrany
  • DFS (depth-first search)
    • prohledávání do hloubky
    • negarantuje nalezení nejlepší cesty
  • BFS (breadth-first-search)
    • prohledávání do šířky, vždy najde nejlepší cestu

Cost-based vyhledávání

  • Dijkstrův algoritmus
    • prozkoumá všechny uzly a najde nejkratší cestu do všech ostatních uzlů
    • používá metriku CSF (cost-so-far)
  • A*
    • rozšíření Dijkstrova algoritmu z roku 1968
    • liší se především v zavedení heuristiky

A*

  • používá odhad ceny do cíle z daného uzlu
  • Cena  F = G + H , kde G  je cost-so-far a H  je heuristický odhad
  • Heuristiky: euklidovská, manhattanská, adaptivní, dynamická,...

Vylepšení

  • různé formy preprocessingu, tvorba univerzálních cest
  • označení slepých uliček
  • jiná granularita než u vizuální herní mapy

Pathfinding algoritmy: porovnání

  • BFS ignoruje cenu
  • Dijkstra ignoruje topologii
  • A* bere v potaz obojí

HPA*: Hierarchický Pathfinding A*

  • používá clusterizaci (rozdělení problému na podproblémy)
  • rozdělí mapu na regiony, se kterými nakládá jako se samostatnými uzly
  • gate - nejdelší hraniční segment bez překážek
  • vyhovující pro většinu her

Co jsme si řekli

  • Něco o uniformních a gaussových distribucích
  • Něco o pojmech jako loot, spinning, rarity slotting a random encounter
  • Něco o šumových funkcích
  • Něco o řídkých 2D strukturách jako grid, quad-tree a oct-tree
  • Něco o pathfinding algoritmech jako je BFS, Dijkstra a A*

Goodbye Quote

Mohu vycvičit experty černé magie na mistry, ovšem jen pokud splňují má kritéria. Budu učit jen opravdové zasvěcence, ty, kteří jsou tak zlí, že jejich reputace je ta nejhorší - prostě opravdové Miloše Zemany. Nedělám žádné výjimky a též nežádám žádné peníze, stačí ujištění, že budete po světě šířit zlo a zvyšovat daně.Might and Magic 6
I can bring experts of dark magic up to master, provided they meet my standards. I only teach the genuinely dedicated - those so evil their reputations are as bad as they can get. The truly notorious. I make no exceptions, and charge no fee in the interests of spreading darkness throughout the world.Might and Magic 6