Witam. Nie znalazłem porządnego tutoriala o allegro 4.2 po polsku(jest beznadziejny tutorial easycodera, który tylko mąci w głowach), więc postanowiłem napisać ten tutorial aby pomóc niektórym w nauce świetnej biblioteki jaką jest Allegro. Pisząc go będę opierać się o allegro 4.2.1 i korzystać z Visual Studio 2008. Zakładam, że znacie C++ oraz sami potraficie ściągnąć bibliotekę i pogodzić z nią swoje środowisko(byle nie Dev C++!). Jeśli nie to się nauczcie. : ) No to zaczynamy. Pierwsza aplikacja Tworzenie okienka allegro, obsługa klawiatury, timery oraz wyświetlanie spritów wykorzystując podwójne buforowanie. Na samym początku includujemy sobie nagłówek allegro.h. Później dodajmy sobie dwa przydatne makra-width oraz HEIGHT oznaczające odpowiednio szerokość oraz wysokość naszego okienka. U mnie będą miały one wartości 800 oraz 600. Teraz pierwsza nowa rzecz: Deklarujemy dwa obiekty bitmap allegro. :) Bitmapy w allegro służą do malowania-nimi oraz po nich. BITMAP *bufor; BITMAP *ryjek; Pierwsza bitmapa to nasz bufor. Będziemy po nim malować, aby potem jednym sprawnym ruchem w błyskawicznie przerzucić cały obraz na ekran unikając efektu migania. Ryjek to nasz obrazek, który wczytamy sobie z pliku. Następnie zadeklarujemy dwie zmienne pomocnicze: zmienną liczbową ticks oraz flagę wyjscie: int ticks=0; bool wyjscie=false; Zmienna ticks posłuży nam tylko i wyłącznie do timera. Więcej o niej później. A flaga wyjscie będzie do podtrzymywania naszej pętli głównej-petla wykonywać się bedzie dopóty dopóki wyjscie==false. :) Dodamy sobie także dwie zmienne: x i y oznaczające pozycję naszego obrazka. float x=100,y=100; Domyślnie ustawiłem je na 100,100. Następnie deklarujemy funkcję timera: Jak widać funkcja jest banalna-jedyne co robi to zwiększa ticks o jeden. Ok, teraz trochę bardziej skomplikowana funkcja init(): void init() allegro_init(); install_keyboard(); set_color_depth(32); set_gfx_mode(gfx_autodetect_windowed, WIDTH, HEIGHT, 0, 0); W skrócie tworzy ona nam nasze okienko allegro oraz inicjuje timer i klawiaturę. Opiszę ją dokładniej. Instrukcja void allegro_init() inicjuje allegro, włącza je. void install_keyboard() mówi bibliotece allegro, że chcemy korzystać z klawiatury. Funkcja void set_color_depth(int depth) ustawia
głębię kolorów naszego programu-wybieramy największą, czyli 32 bity. Następna jest trochę bardziej skomplikowana funkcja set_gfx_mode: int set_gfx_mode(int card, int w, int h, int v_w, int v_h); Pierwszy argument oznacza typ aplikacji jaką chcemy utworzyć-pełnoekranową, czy może w okienku. My chcemy w okienku. Następnie podajemy wymiary naszego okienka-czyli makra które zdefiniowaliśmy na początku. Dwa ostatnie argumenty nie były mi nigdy potrzebne więc zakładam, że Wam również nie będą i pozwolę sobie je pominąć. : ) Ostania instrukcja tworzy nam nasz upragniony timer. int install_int(void (*proc)(), int speed); Jako pierwszy argument pobiera ona wskaźnik do funkcji, która ma być wykonywana co ilość milisekund podanych jako drugi argument. My podajemy tam kolejno funkcję timerproc oraz 30 milisekund. Oznacza to, że funkcja timerproc będzie wykonywana co 30 milisekund. Następnie stworzymy sobię funkcję load(), w którejto 'stworzymy' bufor oraz wczytamy nasz obrazek. Oto ona: void load() bufor=create_bitmap(width,height); ryjek=load_bitmap("ryjek.bmp",null); Tworzenie bufora jest dość proste-wystarczy poprostu nadać mu wartość zwracaną przez banalną funkcję BITMAP *create_bitmap(int width, int height). Jako parametry pobiera ona szerokość oraz wysokość naszej bitmapy. My tworzymy bufor, więc bitmapa ma być rozmiaru okna-można śmiało wykorzystać nasze makra. Ładowanie bitmap jest równie proste-wykorzystamy do tego funkcję BITMAP *load_bitmap(const char *filename, RGB *pal) która jako argumenty pobiera kolejno ścieżkę do pliku oraz dane o palecie. My nie korzystamy z palet, więc podajemy tam NULL. Ok, mamy bitmapki, jesteśmy gotowi maznąć coś na ekranie. Zróbmy to więc. : ) Oto funkcja draw(): void draw() clear_to_color(bufor,makecol(0,0,255)); draw_sprite(bufor,ryjek,x,y); blit(bufor,screen,0,0,0,0,width,height); Na początku czyścimy bufor za pomocą funkcji void clear_to_color(bitmap *bitmap, int color). Jako pierwszy argument podajemy bitmapę, którą chcemy wyczyścic-czyli nasz bufor. Jako drugi zaś kolor, na który chcemy ją wyczyścić. Można się tu posłużyć allegrowską funkcją makecol, która jako argumenty pobiera składowe RGB, co właśnie zrobiłem uzyskując niebieski bufor. Następnie wyświetlamy naszą bitmapkę na czyściutkim buforze za pomocą funkcji void draw_sprite(bitmap *bmp, BITMAP *sprite, int x, int y); Jako pierwszy argument podajemy bitmapę docelową-nasz bufor. Jako drugi bitmapę, którą chcemy wyświetlić-naszą bitmapkę ryjek. Jako trzeci i czwarty podajemy współrzędne, na których chcemy ją wyświetlić-u mnie jest to (100,100). Funkcja ta rysując bitmapkę automatycznie odrzuca kolor (255,0,255), czyli różowy. Dzięki temu można uzyskać obrazki o kształcie innym niż prostokąt. Teraz jednym wprawnym ruchem przerzucamy nasz bufor na ekran wywołując funkcję void blit(bitmap *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); Służy ona do wyświetlania prostokąta wyciętego z jednej bitmapy na drugą. Jako pierwszy argument podajemy bitmapę źródłową, jako drugi-docelową. Jako następne dwa podajemy współrzędne lewego górnego rogu kopiowanego prostokąta, później współrzędne na
bitmapie docelowej na które chcemy wrzucić nasz wycinek, a na końcu szerokość i wysokość naszego prostokąta. Ta funkcja już nie odrzuca różowego koloru. Teraz zrobimy funkcję logic(), czyli jakby serce programu. :) void logic() if(key[key_esc]) wyjscie=true; W tym przypadku serce jest raczej wątłe i słabe, ale silniejszego nie potrzebujemy. ;) W tym miejscu właśnie korzystamy z klawiatury. Otóż allegro posiada tablicę typu bool o nazwie key. Zawiera ona informacje o wciśniętych klawiszach. Kody klawiszy można znaleźć w dokumentacji: http://www.allegro.cc/manual/api/keyboard-routines/key. W naszym programie sprawdzamy, czy został naciśnięty klawisz escape. Jeśli tak, to ustawiamy flagę wyjscie na true. Została nam ostatnia funkcja przed mainem: funkcja release(), w której posprzątamy po programie. void release() destroy_bitmap(ryjek); destroy_bitmap(bufor); allegro_exit(); Dwukrotnie wykorzystujemy tu funkcję void destroy_bitmap(bitmap *bitmap). Jako argument pobiera ona obiekt bitmapy usuwając go z pamięci. Usuwamy obie nasze bitmapki a następnie wyłączamy allegro wywołując funkcję void allegro_exit(). Ok, teraz musimy stworzyć funkcję main(): int main() init(); load(); while(!wyjscie) draw(); while(ticks>0) logic(); ticks--; release(); return 0; END_OF_MAIN(); A teraz pokrótce ją wyjaśnię. Na początku tworzymy okienko, inicjujemy allegro i tworzymy timer wywołując funkcję init(), tworzymy bufor oraz ładujemy obrazek w funkcji load(). W tym momencie wchodzimy w pętlę główną: w każdym obiegu pętli rysujemy to, co mamy do narysowania, oraz co 30 milisekund wywołujemy funkcję logic(). Dlaczego co 30 milisekund? Przypomnijmy sobie nasz timer oraz jego funkcję: (...)
Otóż nasz timer co 30 milisekund zwiększa ticks o 1. Wtedy w pętli głównej wykona się funkcja logic, a ticks zostanie zredukowane do zera. : ) Jeśli wyjscie==true(został wciśnięty klawisz escape) to wychodzimy z pętli, sprzątamy po programie wywołując funkcję release() i wyłączamy program. Tak powinna wyglądać pętla każdej gry w allegro wykorzystującej timery. Zamiast timerów można użyć czegoś dokładniejszego, czyli pętli czasu rzeczywistego. Ale nie sądzę, aby była potrzeba opisywania tego przeze mnie-xion opisał to bardzo dobrze na swoim blogu(google: real time loop). Muszę jednak wspomnieć, że jeśli chcemy korzystać z Winapi w allegro trzeba dołączyć nagłówek winalleg.h PO allegro.h. Należy także pamiętać o umieszczeniu allegrowskiego makra END_OF_MAIN() po funkcji main(). To już wszystko w dzisiejszej lekcji, na koniec dam screena oraz cały kod programu. Jako zadanie dla treningu proponuję spróbować wprawić nasz obrazek w ruch za pomocą strzałek. Trzeba to zrobić zmieniając odpowiednio zmienne x i y w funkcji logic(), najlepiej za pomocą strzałek. :) #include <allegro.h> #pragma comment(lib,"alleg.lib") #define WIDTH 800 #define HEIGHT 600 BITMAP *bufor; BITMAP *ryjek; int ticks=0;
bool wyjscie=false; float x=100,y=100; void init() allegro_init(); install_keyboard(); set_color_depth(32); set_gfx_mode(gfx_autodetect_windowed, WIDTH, HEIGHT, 0, 0); void load() bufor=create_bitmap(width,height); ryjek=load_bitmap("ryjek.bmp",null); void draw() clear_to_color(bufor,makecol(0,0,255)); draw_sprite(bufor,ryjek,x,y); blit(bufor,screen,0,0,0,0,width,height); void logic() if(key[key_esc]) wyjscie=true; void release() destroy_bitmap(ryjek); destroy_bitmap(bufor); allegro_exit(); int main() init(); load(); while(!wyjscie) draw(); while(ticks>0) logic(); ticks--; release(); return 0; END_OF_MAIN();