*
Dzięki temu, że używamy dwóch pętli, można wprowadzić animację czy zmianę koloru napisu.
Plik dla programu Make, który dokona kompilacji naszego pierwszego programu, jest następujący:
all:
gcc -o miniexample miniexample.c
'sdl-config - -1 i bs --cflags' -1S DI__11 f
Skrypt sdl-config dotyczy tylko i wyłącznie biblioteki SDL. Pozostałe biblioteki, ściśle związane z SDL, jak choćby SDL_Ttf, umieszczają własne pliki bibliotek dynamicznych oraz pliki nagłówkowe w tym samych katalogach co SDL. Z tego powodu naszą grę będziemy kompilować w bardzo podobny sposób:
all:
gcc -o statki statki.c 'sdl-config - -1 i bs -cflags'
-1SDL_image -1SDL_ttf -lSDL_net
Tworząc jakikolwiek program, trzeba przyjąć pewne założenia. Zacznijmy od grafiki. Nasza gra będzie pracować w trybie graficznym o rozdzielczości 640x480 w trzydzie-stodwubitowym kolorze. Z tego powodu tworząc grafikę najlepiej przygotowywać pliki (w formacie PNG) w takiej organizacji kolorów. W plikach znajdują się poszczególne fragmenty planszy. Plansza nie jest rysowana ani wczytywana w całości, lecz budowana z owych fragmentów o wymiarach 30x30 pikseli. Taka wartość dobrze komponuje się z wybraną rozdzielczością. Istnieje kilka rodzajów fragmentów, np. fragment pustej planszy czy fragment z kropką, która oznacza, że w nic nie trafiliśmy. Fragmenty oznaczające statki, tak jak widać to na Rysunku 2, oznaczono cyframi, a zatopione zostały dodatkowo przekreślone. Czytelnik może dowolnie zmienić grafikę podmieniając pliki PNG na własne wersje.
Nasza wersja „Gry w statki” pracuje w sieci. Napiszemy jeden program, który będzie pełnił zarówno rolę klienta, jak i serwera - decyzję o tym, jaki tryb zostanie wykorzystany, będzie można podjąć podczas uruchamiania gry.
Program po uruchomieniu w trybie serwera i rozłożeniu statków na planszy będzie nasłuchiwał na zgłoszenie klienta. W trybie klienta, po rozłożeniu przez gracza swojej floty, program będzie próbował połączyć się z serwerem. Czynności, które kolejno wykonuje nasza aplikacja, najlepiej przedstawić za pomocą diagramu przepływu sterowania - Rysunek 3-
Ważny jest sposób prowadzenia gry. Zazwyczaj gracze na zmianę przekazują sobie współrzędne punktu, w który „strzelają”. W naszej wersji można to zmienić wprowadzając statki w wersji czasu rzeczywistego. Każde kliknięcie na planszy będzie oznaczać wykonanie strzału i natychmiast uzyskamy odpowiedź, w co trafiliśmy.
Rysunek 2. Gra w statki
W grze, którą zamierzamy napisać, występują dwa obszary. Pierwszy dotyczy interfejsu gry. Funkcje, która tam się znajdują, mają za zadanie wyświetlić planszę, zarówno naszą, jak i przeciwnika. Do zadań związanych z interfejsem należy również rozstawienie na planszy statków. Z interfejsem związany jest także fakt wczytania plików z grafiką. Drugi obszar to komunikacja sieciowa, do której należy wysyłanie komunikatów sieciowych. Do wysłania danych przez sieć wystarczy wywołanie pojedynczej funkcji. Odbiór będzie wymagał bardziej skomplikowanej obsługi, ponieważ sprawdzamy, czy istotnie są jakieś dane do odbioru, a jeśli takie nie występują, gra może wykonywać inne czynności niezwiązane z siecią.
Pierwsze czynności podejmowane w głównej funkcji to odczytanie argumentów (parametr *argv[] funkcji main), które określają, w jakim trybie ma pracować program: klienta bądź serwera. Następnie wykonywane są czynności związane z inicjalizacją poszczególnych bibliotek. Naturalnie są one identyczne jak w naszym programie „Hello World!”, przy czym oprócz inicjalizacji biblioteki SDLJTtf uruchamiamy także SDL_Image oraz SDL_Net. Następnie włączamy tryb graficzny i wywoływana jest pierwsza funkcja o nazwie DataLoad. Jej podstawowym zadaniem jest wczytanie potrzebnych danych.
Drugą czynnością, która wynika z diagramu na Rysunku 3, jest rozstawienie statków. Realizuje to funkcja DeployFleet. Korzysta ona z pomocniczej funkcji o nazwie DrawFieldlnGame, rysującej planszę. Następnie wykonywana jest funkcja GetYourName. W zależności od tego, czy program jest serwerem, czy klientem, w funkcji oczekujemy na połączenie bądź nasz komputer próbuje łączyć się z innym komputerem.
Po tych czynnościach przechodzimy do gry. Za odświeżanie plansz oraz komunikację sieciową odpowiada funkcja GameLoop. W niej toczy się cała gra. Za większość komunikatów tekstowych, które są wyświetlane na ekranie, odpowiada jedna funkcja - DisplayMesg.
Dokładnie w takiej kolejności, jak powyżej, będę omawiał szczegóły, które kryją się w implementacji. Kolejność
60
grudzień 2003