IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 3 - Grafická knihovna Allegro pro C a C++

V předchozí lekci, Grafická knihovna Allegro pro C a C++, jsme si knihovnu Allegro inicializovali a následně se naučili vykreslovat linky, kružnice, obdélníky a další tvary.

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 - Allegro - Programujeme hry v C++

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++ - Allegro - Programujeme hry 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 - Allegro - Programujeme hry v C++

 

Předchozí článek
Grafická knihovna Allegro pro C a C++
Všechny články v sekci
Allegro - Programujeme hry v C++
Článek pro vás napsal Maxfx
Avatar
Uživatelské hodnocení:
4 hlasů
C,C++
Aktivity