Programowanie gier przy użyciu darmowego kompilatora i biblioteki.
Czy to w ogóle jest możliwe? Okazuje się, że tak, a wszystko dzięki twórcom biblioteki allegro, służącej do pisania gier i programów multimedialnych, jak również aplikacji o własnej architekturze graficznej, którą przy użyciu biblioteki allegro możemy bardzo łatwo stworzyć.
Ogromną zaletą tej biblioteki jest działanie na wielu kompilatorach i systemach operacyjnych.
Znaczy to, więc tyle, że zapalony programista systemu Windows czy Linux może napisać program dla dowolnego z nich, wszystko, czego potrzebujemy to kompilator dla danego systemu operacyjnego i biblioteka allegro. A wszystko za darmo!
Co i jak
Do głównych zadań allegro należy obsługa grafiki, dźwięku, timer'ów, klawiatury, myszki i joystick'a. Dodatkowo biblioteka posiada funkcję do obsługi grafiki 3D, plików, czcionek itp.
Ponadto posiada specjalny format pliku, będącego zasobem, w którym możemy przetrzymywać grafikę, dźwięk itp., czyli wszystko to, co nie powinno być dostępne (do edycji) użytkownikowi naszej gry (aplikacji). Do pisania programów w allegro niezbędna jest znajomość języka C, bez tej wiedzy allegro wydaje się być bezużyteczne. Ktoś może zapytać, a czemu szukać takiego rozwiązania? Odpowiedź jest bardzo prosta. Na całym świecie jest bardzo wielu młodych programistów, którzy mimo swoich ciekawych pomysłów nie mogą zrealizować swoich planów a tym bardziej na nich zarobić, ponieważ koszty związane z zakupem odpowiedniego oprogramowania jest tak wielki, że całe przedsięwzięcie przestaje się opłacać. Tego typu darmowe rozwiązania to dla nich ogromna szansa zrealizowania własnych pomysłów a często nawet marzeń. Opiszemy sposób przygotowania niezbędnych narzędzi dla systemu Windows w celu rozpoczęcia stawiania pierwszych kroków w programowaniu gier przy pomocy darmowych narzędzi. Zaczynamy!
Instalacja kompilatora i biblioteki
Na początku powinniśmy zainstalować darmowy kompilator Dev-C++ firmy Bloodshed Software (najlepiej wersję 4.01), którą możemy pobrać z witryny internetowej lub dołączonej do czasopisma płyty. Możemy również skorzystać z innego darmowego kompilatora my jednak skupimy się na kompilatorze Dev-C++. Następnie ze strony http://www.allegro.cc pobieramy bibliotekę allegro i kilka niezbędnych dodatków zwiększających możliwości kompilatora Dev-C++ (MinGW). Wszystkie pliki (archiwa) rozpakowujemy do folderu zawierającego nasz kompilator. Kolejnym krokiem jest ustawienie ścieżek systemowych w pliku autoexec.bat (Windows 95/98):
SET PATH=C:\Dev-Cpp\bin;%path%
SET MINGDIR=C:\Dev-Cpp
Następnie przechodzimy do katalogu allegro, gdzie wpisujemy poniższe instrukcje: fix mingw32
make all
make install
I to wszystko! Teraz przy pomocy darmowych narzędzi możemy rozpocząć naukę pisania gier.
Pierwszy krok
Otwieramy kompilator Dev-C++, wybieramy File/New Project... i wybieramy Windows Application.
Teraz dodajemy plik liballeg.a. W tym celu przechodzimy do Project/Project Options i wybieramy Load Object Files, ustawiamy pliki typu Lib files i przechodzimy do katalogu Lib kompilatora gdzie wybieramy plik liballeg.a.
Przechodzimy do pliku Untitled1.c, usuwamy wszystkie linijki kodu i umieszczamy poniższy kod:
#include <allegro.h>
int main()
allegro_init();
allegro_exit();
return 0;
}
END_OF_MAIN()
Nasz program inicjuje bibliotekę allegro, następnie bezpiecznie zamyka ją. Jest to ważne w przypadku, gdy uruchamiamy takie urządzenia jak klawiatura, myszka itp., funkcja allegro_exit zadba o ich wyłączenie. Na samym końcu funkcji main umieszczamy zalecane makro END_OF_MAIN(). Jak widzimy biblioteka allegro posiada bardzo czytelne podejście do kwestii kodu i nazw funkcji, dzięki temu uzyskujemy dużą czytelność i szybką orientację w pliku z kodem. Teraz zapoznajmy się z nowymi, niezbędnymi w naszej dalszej pracy funkcjami biblioteki allegro.
Podstawowe funkcje
Pierwszą podstawową funkcją, którą musimy znać to install_keyboard, czyli instalacja obsługi klawiatury (biblioteka allegro podejmuje współpracę z klawiaturą). Kolejna ważna funkcja w pracy z biblioteką to określenie głębi kolorów, w jakiej pracować będzie nasz program.
set_color_depth(int depth);
Argumentem funkcji mogą być takie parametry jak 8 (domyślnie), 15, 16, 24, 32. Wywołujemy ją tylko przed uruchomieniem trybu graficznego, do czego służy funkcja: set_gfx_mode(int card, int w, int h, int v_w, int v_h);
Pierwszy argument może przyjąć jeden z trzech możliwych parametrów:
gfx_autodetect - automatycznie wykryty sterownik
gfx_autodetect_fullscreen - tryb pełno ekranowy
gfx_autodetect_windowed - tryb okienkowy
Drugi i trzeci argument funkcji to szerokość i wysokość ekranu w pikselach. Ostatnie dwa określają parametry ekranu wirtualnego, domyślnie umieszczamy tu zera. Do wyłączenia trybu graficznego na przykład w chwili wykrycia jakiegoś błędu używamy funkcji gfx_text(0,0,0,0).
Następna funkcja na liście do jak najszybszego poznania to set_palette(default palette), czyli standardowa paleta kolorów VGA, stosujemy ją jedynie przy ustawieniu 8 bitowej głębi kolorów, czyli set_color_depth(8). W przypadku korzystania z większej głębi kolorów powinniśmy stosować funkcję makecol(int r, int g, int b), czyli określenie koloru na podstawie składowych RGB (czerwony, zielony, niebieski). Teraz zajmiemy się funkcją clear_to_color(BITMAP
*bitmap, int color), która czyści całą bitmapę wyznaczonym kolorem. Biblioteka allegro w chwili uruchomienia trybu graficznego tworzy bitmapę o nazwie screen, struktura ta znajduje się w pamięci i to, co na niej umieszczamy zostaje wyświetlone na ekranie monitora. Tak jak wcześniej dla podania drugiego parametru możemy użyć funkcji makecol (jeśli pracujemy w trybie powyżej 8 bitów). Do napisania programu pozostaje nam jeszcze poznanie dwóch funkcji:
text_mode i textout. Pierwsza z parametrem -1 umożliwia wyświetlenie tekstu z przeźroczystym tłem, druga umożliwia wyświetlenie tekstu. Funkcja text_out posiada kilka parametrów: wskaźnik do bitmapy, na której tekst ma zostać wyświetlony, czcionka, napis (treść tekstu), pozycja x i y, oraz kolor. Teraz jesteśmy gotowi do napisania pierwszego, bardzo prostego programu. Dla zatrzymania programu użyjemy funkcji readkey, której działanie jest podobne do bardzo popularnej funkcji getch.
#include <allegro.h>
int main()
{
allegro_init();
install_keyboard();
set_color_depth(8);
set_gfx_mode(GFX_AUTODETECT_FULLSCREEN,640,480,0,0);
set_palette(default_palette);
clear_to_color(screen,10);
text_mode(-1);
textout(screen,font,"Witaj w programie napisanym w
Allegro!",170,210,8);
readkey();
allegro_exit();
return 0;
}
END_OF_MAIN()
W tej prostej aplikacji możemy wprowadzić pewną zmianę ulepszającą aplikację, polegającą na sposobie zakończenia programu na przykład po wciśnięciu klawisza Esc. Na przykład w pętli while.
while(!key[KEY_ESC]){
//instrukcje w pętli
}
Jak widzimy wykorzystaliśmy tu nową funkcję o nazwie key. Analogicznie postępujemy z rozpoznawaniem innych klawiszy klawiatury o to kilka przykładów:
KEY_SPACE - spacja
KEY_ENTER - enter
KEY_A ... KEY_Z - poszczególne litery
KEY_F1 ... KEY_F12 - (e)F od 1 do 12
KEY_TAB - tabulator
KEY_LSHIFT - lewy shift
Wszystko jest bardzo przejrzyste i czytelne, dodatkowo biblioteka allegro posiada własny manual, w którym opisane zostały niemal wszystkie funkcje. W razie kłopotów zawsze możemy do niego zajrzeć.
Możemy usunąć już zbędną funkcję readkey a nasz kod programu powinien wyglądać następująco:
#include <allegro.h>
int main()
{
allegro_init();
install_keyboard();
set_color_depth(8);
set_gfx_mode(GFX_AUTODETECT_FULLSCREEN,640,480,0,0);
set_palette(default_palette);
clear_to_color(screen,10);
text_mode(-1);
textout(screen,font,"Witaj w programie napisanym w
Allegro!",170,210,8);
while(!key[KEY_ESC]){
//instrukcje w pętli
}
allegro_exit();
return 0;
}
END_OF_MAIN()
Malowanie po ekranie
Teraz naszą powitalną planszę wzbogacimy o różne elementy graficzne w postaci pojedynczych pikseli, linii, prostokątów, kwadratów, kół, elips itp. Czyli zajmiemy się rysowaniem kształtów przy pomocy dostępnych funkcji, które standardowo oferuje nam biblioteka allegro. Na początek poznajmy funkcję malującą pojedynczy piksel. Przy pomocy tej funkcji możemy namalować dowolne kształty, tak jak byśmy używali "ołówka i gumki".
putpixel(BITMAP *bmp, int x, int y, int color);
Pierwszym argumentem funkcji jest oczywiście wskaźnik do bitmapy, na której chcemy umieścić malowany piksel, drugi i trzeci argument to położenie x i y na ekranie, ostatni argument to oczywiście kolor, dla przykładu funkcja w programie może wyglądać na przykład tak: putpixel(screen, 34,50,makecol(0,255,0));
W miejscu podania koloru użyliśmy znanej nam już funkcji makecol, która zwraca numer koloru na podstawie składowych RGB (funkcja ta pracuje na wartościach od 0 do 255).
Kolejne funkcje, które poznamy to:
vline(BITMAP *bmp, int x, int y1, int y2, int color);
i
hline(BITMAP *bmp, int x1, int y, int x2, int color);
Pierwsza jest odpowiedzialna za namalowanie pionowej linii, druga poziomej. Jest jeszcze jedna funkcja rysująca linię, która może przybrać dowolne położenie kątowe (stąd też posiada o jeden argument więcej).
line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
Jeśli będziemy chcieli namalować trójkąt (zamalowany) posłużymy się funkcją triangle.
triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color) ; Do namalowania prostokąta (zamalowanego) użyjemy funkcji rectfill.
rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
Jeśli będziemy chcieli namalować jedynie prostokątne obramowanie (zarys prostokąta) użyjemy funkcji rect().
rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
Analogicznie postępujemy na przykład z rysowaniem koła (funkcja circlefill, circle), czy elipsy (ellipsefill, ellipse). Biblioteka allegro posiada wiele innych ciekawych funkcji, przy pomocy, których możemy uzyskać najprzeróżniejsze kształty. A teraz wykorzystajmy zdobytą wiedzę na temat podstawowych funkcji malowania i rozbudujmy nasz mały programik.
#include <allegro.h>
int main()
{
allegro_init();
install_keyboard();
set_color_depth(8);
set_gfx_mode(GFX_AUTODETECT_FULLSCREEN,640,480,0,0);
set_palette(default_palette);
clear_to_color(screen,10);
text_mode(-1);
textout(screen,font,"Witaj w programie napisanym w
Allegro!",170,210,8);
for(int i=10; i<480; i=i+10){
putpixel(screen,i,i,0);
putpixel(screen,i+125,i,0);
putpixel(screen,i+250,i,0);
}
int y=0;
for(int i=630; i>160; i=i-10){
y=y+10;
putpixel(screen,i,y,0);
putpixel(screen,i-125,y,0);
putpixel(screen,i-250,y,0);
}
triangle(screen,45,45,25,65,75,65,12);
triangle(screen,400,120,300,160,430,160,4);
triangle(screen,410,130,310,170,440,170,12);
rectfill(screen,140,410,230,440,13);
rectfill(screen,570,190,590,420,9);
rect(screen,570,190,590,420,7);
rectfill(screen,260,300,300,340,2);
rect(screen,420,260,500,340,14);
circlefill(screen,60,190,40,3);
circle(screen,60,190,57,1);
hline(screen,30,220,600,12);
vline(screen,40,40,440,14);
ellipsefill(screen,490,80,100,25,11);
ellipse(screen,490,80,25,60,12);
while(!key[KEY_ESC]){
//instrukcje w pętli
}
allegro_exit();
return 0;
}
END_OF_MAIN()
Na początku malujemy trzy przerywane linie za pomocą pojedynczych pikseli, biegnące od lewego górnego rogu ekranu i trzy od prawego. Rysowanie realizujemy poprzez dwie pętle for.
Następnie malujemy mały trójkąt położony blisko prawego górnego rogu ekranu, oraz dwa nakładające się na siebie trójkąty. W kolejnym kroku malujemy prostokąt (wypełniony kolorem), drugi prostokąt (wypełniony kolorem) i jego obramowanie (zarys). Następnie malujemy kwadrat i sam zarys kwadratu, ale w innym miejscu na ekranie, oraz poziomą i pionową linie. Na samym końcu malujemy dwie elipsy o różnym położeniu, jedna jest wypełniona kolorem, druga jest jedynie jej samym zarysem. Teraz nasz ekran powitalny wygląda znacznie ciekawiej.
Krok dalej
Do tej pory wszystkie nasze figury geometryczne i inne elementy na ekranie posiadały ściśle określaną orientację poziomą i pionową. Nadszedł czas abyśmy dodali coś nie coś pod innym kątem. Posłuży nam do tego funkcja rotate_sprite. Zanim jednak się nią posłużymy musimy zapoznać się z bardzo ważną strukturą w bibliotece allegro, bez której nie moglibyśmy napisać gry. BITMAP to struktura, która przechowuje obraz w pamięci. Jak już wiemy podczas uruchomienia trybu graficznego, allegro tworzy podstawową strukturę BITMAP o nazwie screen.
To, co na niej umieścimy, zostanie wyświetlone na ekranie. Tworzenie struktury BITMAP
realizujemy w poniższy sposób:
BITMAP *wsk_bmp = NULL;
Struktura ta składa się z dwóch elementów. Zmiennej width, określającej szerokość struktury BITMAP, oraz zmiennej height, określającej wysokość. O to przykład tworzenia nowej struktury BITMAP w pamięci:
wsk_bmp = create_bitmap(150,150);
Jak widzimy nie ma w tym nic trudnego, pod koniec programu pozostaje nam jeszcze usunąć zajmowaną pamięć poprzez funkcję destroy_bitmap.
destroy_bitmap(wsk_bmp);
Obracanie na ekranie
Wiemy już, że do obracania elementów możemy zastosować funkcję rotate_sprite. Zapoznajmy się, więc z nią bardziej dokładnie.
rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); Funkcja posiada następujące argumenty: docelowa struktura BITMAP, źródłowa, pozycja x i pozycja y, oraz kąt obrotu.
Zastosujmy ją w praktyce w naszym ekranie powitalnym. Na początku tworzymy nową bitmapę, BITMAP *ob_kwadrat;
jej obiekt w pamięci,
ob_kwadrat = create_bitmap(150,150);
oraz umieszczamy kod usunięcia jej podczas zakończenia pracy programu.
destroy_bitmap(ob_kwadrat);
Następnie wypełniamy nasz ob_kwadrat kolorem tła ekranu.
clear_to_color(ob_kwadrat,2);
Teraz na bitmapie ob_kwadrat rysujemy kwadrat.
rectfill(ob_kwadrat,0,0,200,200,4);
i dodajemy funkcje rotate_sprite.
rotate_sprite(screen,ob_kwadrat,360,260,itofix(40));
Ponieważ kąt musimy podać w zmiennej typu fixed, zastosowaliśmy funkcje zwracającą z liczby typu int typ fixed.
Krótkie podsumowanie
Biblioteka allegro to bardzo wygodne narzędzie do nauki programowania gier i interfejsów aplikacji. Napisanie prostej gry 2D jest dzięki niej stosunkowo proste.
Tomasz Jerzak