3. diel - Grafická knižnica Allegro pre C a C ++
Dnes si ukážeme zložitejšie vykresľovanie v Allegru pomocou sínusu, Cosina, vektorov atď. Začnime s niečím, čo môže byť niekedy ťažko zrozumiteľné pre začiatočníkov - vektor.
Vektor
Vektor môže byť zobrazený rôznymi spôsobmi. Vektor je orientovaná úsečka, má smer a veľkosť. Môžeme si predstaviť, že je to úsečka smerujúce z jedného bodu do druhého iba jedným smerom. V prípade dvoch-rozmerného priestoru budeme potrebovať dve hodnoty definujúce vektor - jednu pre súradnicu X a druhú pre Y súradnicu. V prípade trojrozmerného priestoru budete potrebovať ešte jednu hodnotu a to Z súradnicu. Tento článok sa bude predovšetkým zaoberať dvojrozmerných priestorom, pretože trojrozmerný priestor je zložitejšia a ja nie som žiadny expert.
Na vyššie uvedenom obrázku som nakreslil vektor začínajúce v počiatku súradníc, teda v bode so súradnicami [0,0] - prvé číslo vyjadruje X súradnicu a druhé Y súradnicu. Konečný bod tohto vektora je v bode [3,3]. Ale tieto dve hodnoty nie sú koniec príbehu. Ak napríklad nakreslíme tento vektor na papieri, môžeme zmerať jeho dĺžku do bodu [3,3] a uhol medzi vektorom a osou X, ktorý je 45 stupňov. Ak používate X a Y súradnice, používate Karteziánsky systém súradníc. Ak používate uhol a dĺžku vektora, používate zápis v polárnych súradniciach. Uveďme si príklad. Predstavte si, že píšeme závodná hra a na dráhu sa pozeráme zhora (niečo ako Micro Machines). Budete potrebovať spôsob, ako uložiť rýchlosť a smer pretekárskeho vozidla. A ako to urobíme? Vektorom. Tento vektor rýchlosti je v podstate zmena pozície pretekárskeho vozidla medzi dvoma snímkami. Otázkou je: Mali by sme použiť pravouhlé alebo polárne súradnice tohto vektora?
Karteziánske súradnice majú tú výhodu, že je veľmi ľahké vypočítať novú polohu pretekárskeho vozidla pri každom kroku. Predstavte si, že [X, Y] je uloženie súradnice vektora rýchlosti v premenných vel_x a vel_y a postavenie pretekárskeho automobilu v premenných pos_x a pos_y. Všetko čo musíme urobiť je tu:
pos_x += vel_x; pos_y += vel_y;
Čo môže byť jednoduchšie?
Na druhú stranu - uchovávanie dĺžky a uhla vektora rýchlosti má svoje výhody v tom, že uľahčuje ovládanie pretekárskeho auta. Premýšľajte o tom - ak hráč stlačí na klávesnici šípku vľavo ([KEY_LEFT]), chcete, aby pretekárske auto odbočil vľavo. Predpokladajme, že si ukladáte uhol v premennej car_angle, kde môžete použiť nasledujúci 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 ako to urobíte, ak budú uložené iba xay? Budete musieť zmeniť obaja, ale ako? To je oveľa ťažšie! Okrem toho, ak hráč chce aby pretekárske auto išlo rýchlejšie. Možno to dosiahnuť tým, že jednoducho zvyšuje dĺžku vektora.
Sin & Cos
Dobre, tak teraz vieme, že existujú dva spôsoby, ako uložiť vektor - s polárnymi alebo kartézskými súradnicami - obaja majú svoje výhody. Ktorý z nich vlastne používať? To by nemal byť veľký problém, ak by sme poznali spôsob, ako vypočítať uhol a rýchlosť z osí X a Y a naopak.
Najprv budem hovoriť o konverziu z polárnych do karteziánskych súradníc. Je samozrejme tiež možné prevádzať obrátene, ale o tom budem hovoriť neskôr. K dispozícii sú dve funkcie, ako to dosiahnuť. Tieto funkcie sú sínus a kosínus (sin a cos). Nevedeli ste, že to príde, že nie?
Sinus možno použiť pre výpočet Y súradnice vektora a cosinus možno použiť pre výpočet X súradnice. Funkcia sin () a cos () majú iba jeden parameter: uhol. Vracia hodnotu medzi -1 a 1. Vynásobte Ak toto číslo podľa dĺžky vektora, získate presné karteziánske súradnice vektora. Takže váš kód bude vyzerať takto:
speed_x = speed_length * cos (speed_angle); speed_y = speed_length * sin (speed_angle);
Pre závodnú hru si uložíte uhol a dĺžku vektora rýchlosti. Môžete tieto hodnoty upraviť podľa hráčovho vstupu a vypočítať X a Y súradnice, keď ste pripravení aktualizovať pozíciu pretekárskeho vozidla.
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; }
A tu máme výsledok ...
O radiánoch
Ale čo je to? Po prvé, prečo to hovorím: while (angle <2 * PI)? Čo to má znamenať? A prečo je angle_stepsize takto nízka hodnota? Človek by si myslel, že s tak nízkou hodnotou, že body na kruhu budú veľmi blízko seba, ale nie sú. Ako to vysvetlíme?
Odpoveď je, že sin a cos funkcie neberú pravidelné stupňa, ktoré by mohli byť použité ako argument. To, že je 360 stupňov v kruhu - toto číslo je myšlienka, ku ktorej prišli zo starého odhadu počtu dní v roku. Ale sin a cos funkcie požadujú hodnotu uhla v radiánoch, nie stupňoch. K dispozícii je 2 * PI radiánu v kruhu, PI je matematická konštanta, zhruba 3,1415927. Takže zhruba 6,282 radiánu zodpovedá 360 °. Ak chceme, môžeme vypočítať počet stupňov z počtu radiánov a naopak. Robíme to takto:
stupna = Radian * 180 / PI; Radian = stupna * PI / 180;
Pozrime sa na náš uhlový prírastok 0,1 v radiánoch: 0,1 radiány = 0,1 * 180 / 3,142 = 5,7 °.
V skutočnosti dôvodom pre zavedenie radiánov je nasledujúci. Dĺžka obvodu kruhu jednotky (kružnica s polomerom 1) je presne 2 * PI. To znamená, že dĺžka obvodu je presne rovnaký počet radiánov v uzavretom kruhu. Získame nejaký prospech z tohto poznania? Nie, ale matematici si myslí, že je to skvelé. Programátori si to nemyslia, teda ak netvorí programy, ktoré sú matematicky oveľa pokročilejšie, než to, čo robíme. Neskôr uvidíme, čo si dobrí programátori (ako Shawn Hargreaves) myslí, že je lepší spôsob, ako definovať uhol pre väčšinu aplikácií.
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 tu vidíte, ako programátori niekedy využívajú uhly: využívajú kruhu, ktorý je rozdelený do 256 častí, v rozsahu od 0 do 255, ale nie hodnotu 256 samotnú. Hovorme týchto častiam - Allegro-stupňa, (aj keď tento systém nie je vynález Allegra, ako názov napovedá). Prečo 256 a nie 360? Tak tu je tá vec. Čo sa stane, keď máte uhol 361 stupňov? Vzhľadom k tomu, kruh je guľatý (podľa definície), 361 stupňov predstavuje rovnaké miesto ako 1 stupeň. V podstate rovnakým spôsobom, 3 * PI radiánov je rovnaký ako 1 * PI radiánov, a 257 stupňov Allegro je rovnaký ako 1 stupeň Allegro. Ak chcete skontrolovať uhly merané v stupňoch a previesť ich na správny rozsah, budeme musieť urobiť niečo takéto:
int angle_in_degrees; while (angle_in_degrees >= 360) angle_in_degrees -= 360; while (angle_in_degrees < 0) angle_in_degrees += 360;
Ale pretože Allegro má rozsah od 0 do 255, pričom tento rozsah môže byť uložený v presne 8 bitoch (v prípade int), budeme potrebovať iba resetovať všetky ostatné bity a môžeme si byť istí, že máme čistý uhol v rozsahu od 0 až 255. len sa musíme demaskovať všetky bity s výnimkou dolných 8 bitov. Môžeme to urobiť pomocou bitového operátora AND (&):
int allegro_degrees; allegro_degrees &= 0xFF; // zachová nejnižších 8 bitů
Pre tých, ktorí presne nechápu bitový AND (&) operátor: Verte mi, je to veľmi jednoduchý spôsob, ako sa uistiť, že uhol je v dosahu. Stačí použiť vyššie uvedený kód a môžete si byť absolútne istí, že je uhol medzi 0 a 255.
Ak budeme používať pevný počet hodnôt (fixed point) na vyjadrenie stupňov musíme to urobiť trošku inak, pretože máme aj 16 bitov reprezentujúci časť za desatinnou čiarkou. Takže to, čo musíme urobiť, je takmer presne to isté, je miesto 8 bitov zachováme 16 + 8 = 24 bitov. Tu je to, čo robíme:
fixed allegro_degrees; allegro_degrees &= 0xFFFFFF; // zachová nejnižších 24 bitů
Ak pochopíte toto, potom pochopíte prečo 256 stupňová škála je často najlepšie pre herné programátorov. Pamätajte: bežne ľudia používajú štandardné stupňa, matematici používajú radiány a herné programátori používajú Allegro-stupňa. Dobrá, možno je to príliš zjednodušené. Ak používate float, je lepšie používať radiány, pretože goniometrické funkcie sin () a cos () používajú hodnoty v radiánoch. Ak používate fixed, ako bolo ukázané vo väčšine prípadov, je lepšie používať Allegro-stupňa, pretože funkcia FSIN () a fcos () ich používajú a môžeme udržať hodnoty uhla v rozmedzí s jednoduchým bitovým AND. Rovnako ako sme prevádzali radiány a stupňa, môžeme vypočítať počet Allegro-stupňov z radiánov a štandardné stupňa. Tu je bez ďalšieho vysvetľovania, ako to urobiť:
allegro_degrees = regular_degrees * 256 / 360; allegro_degrees = radians * 128 / PI;
Pre lepšiu predstavu čo sínus a kosínus vlastne robia som napísal nasledujúce funkciu:
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; }
Tu je výsledok:
Pokračovanie v ďalšom dieli ...