Herní návrhový vzor Rozdělení snímku

Z CHWiki

Přejít na: navigace, hledání

Obsah

Účel

Zpřesnění fyzikálních výpočtů

Jiné názvy

Nejsou známy

Motivace

Při numerických výpočtech fyziky nestačí provádět jeden výpočet každý snímek, protože příliš dlouhý časový krok způsobuje něpřesnosti jako prolínání objektů nebo průchod objektů skrz sebe bez kolize. Proto se měří časový interval od posledního snímku a pokud je příliš velký, provede se několik výpočtů.

Použití

Vzor Rozdělení snímku použijeme, pokud chceme ve hře implementovat přesnou fyziku. Jeden výpočet za sekundu stačí jen pro úplně základní detekci kolizí.

Důsledky

V důsledku několika fyzikálních výpočtů každý snímek je hra náročnější na výpočetní výkon počítače. Na druhou stranu dosáhneme funkční a vcelku stabilní fyzikální simulace.

Implementace

Implementace je vcelku snadná, stačí v každém snímku vypočítat časový krok a v případě potřeby provést opakovaně výpočet, viz příklad.

Příklad

Téměř kompletní implementace měření časového intervalu a rozdělení snímku v jazyce C++:

// tato konstanta urcuje maximalni mozny interval mezi dvema fyzikalnimi
// vypocty v milisekundach
const float maxDelta = 30;
// do teto promenne se uklada aktualni cas v milisekundach
float now;
// tato promenna slouzi k uchovani casu posledniho snimku
float lastTime = 0;

void doPhysicsInTime(float time) {
    // tato funkce spocita stav objektu v case time
    // alternativou je posilat jen cas uplynuly od posledniho vypoctu
}

void Update() {
   // kolik casu uplynulo od posledniho update
   float deltaTime = now - lastTime;    
   // vzdy delame alespon 1 vypocet
   int iterations = 1;                  
   // pokud uplynulo vice casu nez je maximum
   if (deltaTime > maxDelta)            
       // vypocitame pocet opakovani vypoctu
       iterations = (int)(deltaTime / maxDelta) + 1; 
   // vypocitame interval mezi jednotlivymi opakovani vypoctu
   float iterDelta = deltaTime / iterations;         
   for (int i = 0; i < iterations; i++) {
       // vypocitame cas vypoctu i-teho opakovani
       float newNow = lastTime + (i + 1) * iterDelta;   
       // spustime vypocet fyziky v dobe newNow
       doPhysicsInTime(newNow);              
   }
   // zapamatujeme si aktualni cas pro vypocet rozdilu v dalsim snimku 
   lastTime = now;                     

}

Známá použití

Všechny fyzikální enginy - ODE,...

Příbuzné vzory

Odkazy