3. díl - Grafická knihovna Allegro pro C a C++

C++ Allegro Grafická knihovna Allegro pro C a C++

Dnes si ukážeme složitější vykreslování v Allegru pomocí sinu, cosinu, vektorů atd. Začněme s něčím, co může být někdy obtížně srozumitelné pro začátečníky - vektor.

Vektor

Vektor může být zobrazen různými způsoby. Vektor je orientovaná úsečka, má směr a velikost. Můžeme si představit, že je to úsečka směřující z jednoho bodu do druhého pouze jedním směrem. V případě dvou-rozměrného prostoru budeme potřebovat dvě hodnoty definující vektor - jednu pro souřadnici X a druhou pro Y souřadnici. V případě trojrozměrného prostoru budete potřebovat ještě jednu hodnotu a to Z souřadnici. Tento článek se bude především zabývat dvourozměrným prostorem, protože trojrozměrný prostor je složitější a já nejsem žádný expert.

Vektor v 2d prostoru

Na výše uvedeném obrázku jsem nakreslil vektor začínající v počátku souřadnic, tedy v bodu se souřadnicemi [0,0] – první číslo vyjadřuje X souřadnici a druhé Y souřadnici. Konečný bod tohoto vektoru je v bodě [3,3]. Ale tyto dvě hodnoty nejsou konec příběhu. Pokud například nakreslíme tento vektor na papíře, můžeme změřit jeho délku do bodu [3,3] a úhel mezi vektorem a osou X, který je 45 stupňů. Používáte-li X a Y souřadnice, používáte kartézský systém souřadnic. Používáte-li úhel a délku vektoru, používáte zápis v polárních souřadnicích. Uveďme si příklad. Představte si, že píšeme závodní hra a na dráhu se díváme shora (něco jako Micro Machines). Budete potřebovat způsob, jak uložit rychlost a směr závodního vozu. A jak to uděláme? Vektorem. Tento vektor rychlosti je v podstatě změna pozice závodního vozu mezi dvěma snímky. Otázkou je: Měli bychom použít pravoúhlé nebo polární souřadnice tohoto vektoru?

Kartézské souřadnice mají tu výhodu, že je velmi snadné vypočítat novou polohu závodního vozu při každém kroku. Představte si, že [X,Y] je uložení souřadnice vektoru rychlosti v proměnných vel_x a vel_y a postavení závodního automobilu v proměnných pos_x a pos_y. Vše co musíme udělat je zde:

pos_x += vel_x;
pos_y += vel_y;

Co může být jednodušší?

Na druhou stranu - uchovávání délky a úhlu vektoru rychlosti má své výhody v tom, že usnadňuje ovládání závodního auta. Přemýšlejte o tom - pokud hráč stiskne na klávesnici šipku vlevo ([KEY_LEFT]), chcete, aby závodní auto odbočilo vlevo. Předpokládejme, že si ukládate úhel v proměnné car_angle, kde můžete použít následující kód:

if ( key [KEY_LEFT])
car_angle - = 1, / / zase jeden stupeň doleva
}
if (key [KEY_RIGHT])
{
car_angle + = 1, / / zase jeden stupeň doprava
}

A jak to uděláte, pokud budou uloženy pouze x a y? Budete muset změnit oba, ale jak? To je mnohem obtížnější! Kromě toho, pokud hráč chce aby závodní auto jelo rychleji. Lze toho dosáhnout tím, že prostě zvyšuje délku vektoru.

Sin & Cos

Dobře, tak teď víme, že existují dva způsoby, jak uložit vektor - s polárními nebo kartézskými souřadnicemi - oba mají své výhody. Který z nich vlastně používat? To by neměl být velký problém, pokud bychom znali způsob, jak vypočítat úhel a rychlost z os X a Y a naopak.

Nejprve budu mluvit o konverzi z polárních do kartézských souřadnic. Je samozřejmě také možné převádět obráceně, ale o tom budu mluvit později. K dispozici jsou dvě funkce, jak toho dosáhnout. Tyto funkce jsou sinus a cosinus (sin a cos). Nevěděli jste, že to přijde, že ne?

Sinus lze použít pro výpočet Y souřadnice vektoru a cosinus lze použít pro výpočet X souřadnice. Funkce sin() a cos() mají pouze jeden parametr: úhel. Vrací hodnotu mezi -1 a 1. Vynásobíte-li toto číslo podle délky vektoru, získáte přesné kartézské souřadnice vektoru. Takže váš kód bude vypadat takto:

speed_x = speed_length * cos (speed_angle);
speed_y = speed_length * sin (speed_angle);

Pro závodní hru si uložíte úhel a délku vektoru rychlosti. Můžete tyto hodnoty upravit dle hráčova vstupu a vypočítat X a Y souřadnice, když jste připraveni aktualizovat pozici závodního vozu.

int x, y;
int length = 200; // zde zvětšujeme kruh
float angle = 0.1; // úhel
float angle_stepsize = 0.01; // čím menší, tím menší krok

// projdi všechny úhly od 0 do 2 * PI radians
while (angle < 2 * M_PI) {
    // výpočet X a Y hodnoty vektoru se známou délkou a úhlem
    x = length * cos (angle);
    y = length * sin (angle);
             //putpixel (bitmap,x,y,color)
    putpixel (screen,x + SCREEN_W / 2, y + SCREEN_H / 2, makecol (255, 255, 255));
    angle += angle_stepsize;
}
Kruh pomocí siun a cos v C++

A zde máme výsledek...

O radiánech

Ale co je to? Za prvé, proč to říkám: while(angle < 2 * PI)? Co to má znamenat? A proč je angle_stepsize takto nízká hodnota? Člověk by si myslel, že s tak nízkou hodnotou, že body na kruhu budou velmi blízko sebe, ale nejsou. Jak to vysvětlíme?

Odpověď je, že sin a cos funkce neberou pravidelné stupně, které by mohly být použity jako argument. To, že je 360 stupňů v kruhu - toto číslo je myšlenka, ke které přišli ze starého odhadu počtu dnů v roce. Ale sin a cos funkce požadují hodnotu úhlu v radiánech, nikoli stupních. K dispozici je 2 * PI radiánu v kruhu, PI je matematická konstanta, zhruba 3,1415927. Takže zhruba 6,282 radiánu odpovídá 360°. Chceme-li, můžeme vypočítat počet stupňů z počtu radiánů a naopak. Děláme to takto:

stupne = radiany * 180 / PI; radiany = stupne * PI / 180;

Podívejme se na náš úhlový přírůstek 0,1 v radiánech: 0,1 radiány = 0,1 * 180 / 3,142 = 5,7 °.

Ve skutečnosti důvodem pro zavedení radiánů je následující. Délka obvodu jednotkové kružnice (kružnice o poloměru 1) je přesně 2 * PI. To znamená, že délka obvodu je přesně stejný počet radiánů v uzavřeném kruhu. Získáme nějaký prospěch z tohoto poznání? Ne, ale matematici si myslí, že je to skvělé. Programátoři si to nemyslí, tedy pokud netvoří programy, které jsou matematicky mnohem pokročilejší, než to, co děláme. Později uvidíme, co si dobří programátoři (jako Shawn Hargreaves) myslí, že je lepší způsob, jak definovat úhel pro většinu aplikací.

int length = 60;
fixed x, y;
fixed angle = 5;
fixed angle_stepsize = itofix(5);

while (fixtoi(angle) < 256) {
    // the angle is plotted along the x-axis
    x = angle;
    // the sine function is plotted along the y-axis
    y = length * fsin(angle);
    putpixel(screen, fixtoi (x), fixtoi (y) + SCREEN_H / 2, makecol (255, 255, 255));
    angle += angle_stepsize;
}

Tak tady vidíte, jak programátoři někdy využívají úhly: využívají kruhu, který je rozdělen do 256 částí, v rozsahu od 0 do 255, ale ne hodnotu 256 samotnou. Říkejme těchto částem - Allegro-stupně, (i když tento systém není vynález Allegra, jak název napovídá). Proč 256 a ne 360? Tak tady je ta věc. Co se stane, když máte úhel 361 stupňů? Vzhledem k tomu, kruh je kulatý (podle definice), 361 stupňů představuje stejné místo jako 1 stupeň. V podstatě stejným způsobem, 3 * PI radiánů je stejný jako 1 * PI radiánů, a 257 stupňů Allegro je stejný jako 1 stupeň Allegro. Chcete-li zkontrolovat úhly měřené ve stupních a převést je na správný rozsah, budeme muset udělat něco takového:

int angle_in_degrees;
while (angle_in_degrees >= 360) angle_in_degrees -= 360;
while (angle_in_degrees < 0) angle_in_degrees += 360;

Ale protože Allegro má rozsah od 0 do 255, přičemž tento rozsah může být uložen v přesně 8 bitech (v případě int), budeme potřebovat pouze resetovat všechny ostatní bity a můžeme si být jisti, že máme čistý úhel v rozsahu od 0 až 255. Jen se musíme demaskovat všechny bity s výjimkou dolních 8 bitů. Můžeme to udělat pomocí bitového operátoru AND (&):

int allegro_degrees;
allegro_degrees &= 0xFF; // zachová nejnižších 8 bitů

Pro ty, kteří přesně nechápou bitový AND (&) operátor: Věřte mi, je to velmi jednoduchý způsob, jak se ujistit, že úhel je v dosahu. Stačí použít výše uvedený kód a můžete si být absolutně jisti, že je úhel mezi 0 a 255.

Pokud budeme používat pevný počet hodnot (fixed point) k vyjádření stupňů musíme to udělat trošku jinak, protože máme i 16 bitů reprezentující část za desetinnou čárkou. Takže to, co musíme udělat, je téměř přesně totéž, je místo 8 bitů zachováme 16 + 8 = 24 bitů. Zde je to, co děláme:

fixed allegro_degrees;
allegro_degrees &= 0xFFFFFF; // zachová nejnižších  24 bitů

Pokud pochopíte toto, pak pochopíte proč 256 stupňová škála je často nejlepší pro herní programátory. Pamatujte: běžně lidé používají standardní stupně, matematici používají radiány a herní programátoři používají Allegro-stupně. Dobrá, možná je to příliš zjednodušeno. Pokud používáte float, je lepší používat radiány, protože goniometrické funkce sin() a cos() používají hodnoty v radiánech. Pokud používáte fixed, jak bylo ukázáno ve většině případů, je lepší používat Allegro-stupně, protože funkce fsin() a fcos() je používají a můžeme udržet hodnoty úhlu v rozmezí s jednoduchým bitovým AND. Stejně jako jsme převáděli radiány a stupně, můžeme vypočítat počet Allegro-stupňů z radiánů a standardní stupně. Tady je bez dalšího vysvětlování, jak to provést:

allegro_degrees = regular_degrees * 256 / 360;
allegro_degrees = radians * 128 / PI;

Pro lepší představu co sinus a cosinus vlastně dělají jsem napsal následující funkci:

int length = 50;
fixed x, y;
fixed angle = 0;
fixed angle_stepsize = itofix (5);

while (fixtoi(angle) < 256)
{
    // the angle is plotted along the x-axis
    x = angle;
    // the sine function is plotted along the y-axis
    y = length * fsin (angle);

    putpixel (screen,
        fixtoi (x), fixtoi (y) + SCREEN_H / 2,
        makecol (255, 255, 255));

    angle += angle_stepsize;
}

Zde je výsledek:

Sinus

Pokračování v dalším dílu...


 

  Aktivity (1)

Článek pro vás napsal Maxfx
Avatar
C,C++,C#

Jak se ti líbí článek?
Celkem (3 hlasů) :
55555


 


Miniatura
Všechny články v sekci
Allegro - Programujeme hry v C++

 

 

Komentáře
Zobrazit starší komentáře (6)

Avatar
Lukáš Hruda (Luckin):

Ještě jsem zapomněl napsat, že pomocí operátoru * lze získat i skalární součin dvou vektorů.

 
Odpovědět 18.6.2013 19:58
Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:

Máš jí tady. Ještě se chci zeptat, zda sem nechceš hodit zdroják té vaší střílečky, případně z toho udělat třeba seriál :)

Odpovědět 24.6.2013 18:53
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Maxfx
Redaktor
Avatar
Maxfx:

sakra jak se odebírá komentář ? :D

Odpovědět 24.6.2013 19:05
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Avatar
Jiří Gracík
Redaktor
Avatar
Odpovídá na Maxfx
Jiří Gracík:

Neodebírá :P příště klikni na odeslat pouze jednou, i pokud se ta stránka nenačte, tak mi (nevím jestli i ostatním) to dost často stejně odešle ;)

Odpovědět 24.6.2013 19:08
Creating websites is awesome till you see the result in another browser ...
Avatar
Maxfx
Redaktor
Avatar
Odpovědět 24.6.2013 19:09
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Avatar
Alexei Krylov:

Pokračování asi nebude? Chtěl bych český tutoriál na hru nebo engine v C++ ..

Odpovědět 5.5.2014 16:44
Úžasná hra v C++ http://urw.fi/
Avatar
Maxfx
Redaktor
Avatar
Odpovídá na Alexei Krylov
Maxfx:

Ano píšeme opensource Engine s OpenGL,(i když Engine je široký pojem) pokud se chceš přidat klidne mmužeš
https://bitbucket.org/…ne/wiki/Home

Odpovědět 5.5.2014 18:04
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Avatar
Maxfx
Redaktor
Avatar
Odpovídá na Alexei Krylov
Maxfx:

Ale doporučuji používat allegro 5 , protože 4 je stará jak jeruzalém.

Odpovědět  +1 5.5.2014 18:09
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Avatar
Maxfx
Redaktor
Avatar
Odpovídá na Alexei Krylov
Maxfx:

Ale doporučuji používat allegro 5 , protože 4 je stará jak jeruzalém.

Odpovědět 5.5.2014 18:09
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Avatar
Zdeněk Pavlátka
Tým ITnetwork
Avatar
Odpovídá na Maxfx
Zdeněk Pavlátka:

Nejde jen o stáří, allegro 5 je mnohem propracovanější, rychlejší a snadnější na použití.

Odpovědět 5.5.2014 18:29
Kolik jazyků umíš, tolikrát jsi programátor.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 16. Zobrazit vše