FPS: Konstantnφ rychlost animace

FPS je zkratka z poΦßteΦnφch pφsmen slov Frames Per Pixel, kterß by se dala do ΦeÜtiny p°elo₧it jako poΦet snφmk∙ za sekundu. Tato t°i pφsmena jsou spßsou p°i spouÜt∞nφ program∙ na r∙zn²ch poΦφtaΦφch. Vezm∞te si hru, kterou programßtor zaΦßteΦnφk vyvφjφ doma na svΘm poΦφtaΦi o rychlosti, °ekn∞me, Pentium II. Dß ji kamarßdovi, aby se na ni podφval a zhodnotil. Kamarßd mß doma P4, spustφ ji a vÜe je Üφlen∞ rychlΘ. Dφky FPS se toto nikdy nestane, na jakΘmkoli poΦφtaΦi p∙jde hra v₧dy stejn∞ rychle.

Zßkladem vÜeho je Φas, kter² ub∞hl mezi jednotliv²mi pr∙chody renderovacφ funkcφ. Uvedu p°φklad. Mßme raketu, kterß mß let∞t °ekn∞me 50 jednotek za sekundu. Vφme, ₧e mezi tφmto a p°edchozφm vykreslenφm ub∞hlo 0,1s, tak₧e ji posuneme o 5 jednotek. Tφmto zp∙sobem budou posuny objekt∙ v animaci za urΦit² Φas v₧dy konstantnφ, nezßvisφ na rychlosti poΦφtaΦe ani aktußlnφ zßt∞₧i procesoru.

V²sledkem celΘho tohoto Φlßnku bude velmi jednoduchß t°φda, kterß vÜechny pot°ebnΘ operace implementuje a ukßzka jejφho pou₧itφ.

T°φda FPS obsahuje t°i atributy: Φas p°i minulΘm pr∙chodu vykreslovacφ funkcφ, aktußlnφ Φas a hodnotu FPS. O aktualizaci prom∞nn²ch se starß funkce VypocetFPS(), kterß se musφ volat stejn∞ Φasto jako p°ekreslenφ scΘny, nejlΘpe p°φmo ve funkci, kterß ho mß na starosti. GetFPS() je vlo₧eno z d∙vodu zapouzd°enosti dat.

class FPS// T°φda FPS

{

private:

unsigned int stary_cas;

unsigned int aktualni_cas;

double fps;// PoΦet snφmk∙ za sekundu

public:

void Vypocet();// Volat p°ed ka₧d²m p°ekreslenφm scΘny

inline double GetFPS();// Kv∙li zapouzd°enosti dat

{

return fps;

}

};

Pro zφskßnφ aktußlnφho Φasu m∙₧eme pou₧φt libovolnou funkci. Ve Windows se v∞tÜinou pou₧φvß GetTickCount(), kterß vracφ poΦet milisekund od spuÜt∞nφ systΘmu. Proto₧e jsem zaΦal p°i programovßnφ pou₧φvat knihovnu SDL (Umo₧≥uje snadnΘ portovßnφ aplikace do r∙zn²ch operaΦnφch systΘm∙ - Linux, Win, Mac OS, BeOS, FreeBSD...), pou₧iji v tomto Φlßnku SDL_GetTicks(), kterß vracφ poΦet milisekund od inicializace SDL. V²poΦet FPS je velmi jednoduch². P°evedeme rozdφl Φas∙ na sekundy a vyd∞lφme jφm jedniΦku, kterß reprezentuje jedno vykreslenφ. Na konci p°i°adφme starΘmu Φasu aktußlnφ Φas.

void FPS::Vypocet()

{

aktualni_cas = SDL_GetTicks();// Vrßtφ poΦet milisekund od inicializace SDL

// aktualni_cas = GetTickCount();// SpecifickΘ pro Windows

fps = 1.0 / ((aktualni_cas - stary_cas) / 1000.0);// PoΦet snφmk∙ za sekundu

stary_cas = aktualni_cas;// Pro dalÜφ pr∙chod

}

Jak pou₧φt tuto t°φdu? ╪ekn∞me, ₧e v OpenGL pot°ebujeme krychli, kterß rotuje o 45░ za sekundu. P°i ka₧dΘ aktualizaci ·hlu natoΦenφ k n∞mu p°iΦteme pln²ch 45░, kterΘ ale musφme vyd∞lit hodnotou FPS. JednotlivΘ posuny se rozfßzujφ tak, aby za sekundu byla krychle natoΦenß o po₧adovan²ch 45░.

FPS fps;// Objekt t°φdy

double uhel = 0.0;// ┌hel natoΦenφ krychle

void DrawGLScene(GLvoid)// Vykreslovßnφ

{

fps.Vypocet();// Aktualizace FPS

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Vyma₧e obrazovku a hloubkov² buffer

glLoadIdentity();// Reset matice

glTranslated(0.0, 0.0, -6.0);// Posun do hloubky

glRotated(uhel, 0.0, 1.0, 0.0);// OtoΦφ krychli v zßvislosti na FPS

// Vykreslenφ krychle

uhel += 45.0 / fps.GetFPS();// Aktualizace ·hlu natoΦenφ v zßvislosti na FPS

}

Je nutnΘ poznamenat, ₧e nic nenφ idßlnφ. Pokud by jedno vykreslenφ bylo tak nßroΦnΘ, ₧e by trvalo, p°e₧enu, deset sekund, rychlost by sice z∙stala na konstantnφch 45░ za sekundu, ale vykreslovalo by se a₧ po cel²ch deseti sekundßch (FPS = 0,1). Dovedete si p°edstavit to trhßnφ?! Obecn∞ se °φkß, ₧e by FPS nikdy nem∞lo klesnout pod 30. Nic nßm nebrßnφ, abychom vlo₧ili za v²poΦet FPS podmφnku if(fps.GetFPS < 30) sni₧ kvalitu renderingu; Mohlo by jφm b²t nap°φklad zm∞na kvality textur GL_LINEAR na GL_NEAREST, vypnutφ antialiasingu, odstran∞nφ n∞kter²ch efekt∙ a podobn∞.

FPS vÜak nenφ jedinou mo₧nostφ, jak zajistit plynulost animace. M∙₧eme mφt systΘmov² timer (ve Windows zprßva WM_TIMER), kter² periodicky volß renderovacφ funkci. Tuto techniku osobn∞ pou₧φvßm jen kdy₧ nenφ ₧ßdnß jinß mo₧nost (v₧dy je jinß mo₧nost), proto₧e automatickΘ vykreslovßnφ v hlavnφ smyΦce je v₧dy rychlejÜφ a spolehliv∞jÜφ. Pokud nastavφte timer na moc krßtk² Φas (cca. 50 ms a mΘn∞), budou se vφcenßsobn∞ poslanΘ zprßvy mazat. Aby nedoÜlo k zahlcenφ fronty zprßv, systΘm do nφ nikdy neumφstφ vφce ne₧ jednu zprßvu WM_TIMER. Ostatnφ se neberou v ·vahu, jako by se v∙bec neposlali.

napsal: Michal Turek - Woq

ZdrojovΘ k≤dy