V
Tabela 1. Funkcje i ich przeznaczenie
Funkcja |
Przeznaczenie |
WaitForKeyPressBIock |
funkcja czeka na wciśnięcie jakiegoś klawisza |
isLostGame |
sprawdzenie, czy przegraliśmy, tzn. zostały zatopione wszystkie nasze statki |
ValidPos |
sprawdzenie, czy można postawić statek na planszy pod określonymi współrzędnymi |
DataLoad |
wczytywanie danych |
DrawFieldlnGame |
rysowanie planszy |
DisplayMesg |
wyświetlanie komunikatów |
DeployFIeet |
funkcja, która zajmuje się rozłożeniem statków na planszy |
GetYourName |
funkcja oczekuje na połączenie, jeśli program pracuje jako serwer, bądź próbuje się połączyć z serwerem, gdy gra działa jako klient |
GameLoop |
główna pętla gry - to tu „toczy się" gra |
pos_x=((event.moti on.x)-_off_x)/30; pos_y=((event.motion.y)-_off_y)/30
Zmienne _off_x i _off_y zawierają współrzędne pozycji, od której rysowana jest plansza. W programie są to wartości odpowiednio 150 i 50. Załóżmy, że w zmiennej zawierającej zdarzenie event zarejestrowano przesunięcie myszy i znajduje się tam wartość 200 oraz 150. W zmiennych pos_x i pos_y znajdą się współrzędne pola na planszy w zakresie od zera do dziewięciu, bo gramy na planszy o wymiarach 10 na 10. Dla podanych wcześniej wartości będą to wielkości 1 i 3. Będzie tak, ponieważ dzielenie jest całkowite i dokładnie o taki typ dzielenia nam chodzi. Wartość 30 to oczywiście wymiary pojedynczego pola.
Ważną rzeczą, o której trzeba pamiętać, to niedopuszczenie, aby statek „wypłynął” poza planszę. Z tego powodu, w zależności od wartości type_pos, która zawiera informacje o tym, czy statek kładziemy poziomo bądź pionowo, odpowiednio zmniejszamy wartość pos_x albo pos_y.
W naszej grze obsługa sieci rozpoczyna się w funkcji o nazwie GetYourName. Powinniśmy w niej podać nasze imię oraz adres serwera, do którego chcemy się podłączyć. Adres serwera oraz tryb pracy programu podajemy jako parametry podczas wywoływania programu.
Pierwszą czynność, którą wykonamy, jest utworzenie tzw. zbioru gniazdek (ang. socket set). Przy pomocy zbiorów w SDL_Net można badać, czy określone gniazdka mają jakieś dane do odbioru, czyli czy są aktywne. Podczas tworzenia zbioru podajemy również, ile elementów będzie należeć do zbioru:
clc_set=SDLNet_Al1ocSocketSet(1); srv_set=SDLNet_Al1ocSocketSet(2);
W funkcji GetYourName tworzone są gniazdka typu TCP. Jeśli program pracuje jako klient, uzyskanie połączenia do serwera jest następujące (pominięta została obsługa błędów):
SDLNet_ResolveHost(&ip, remote_host, port) cl i ent=SDLNet_TCP_Open(&i p);
Pierwsza funkcja zamienia symboliczną nazwę zawartą w remote_host na odpowiedni adres IP. Zmienna zawierająca adres IP jest używana w drugiej funkcji do nawiązania połączenia. Jeśli nie pojawiły się błędy, to wystarczy jeszcze dodać otrzymane gniazdo do zbioru clc_set:
SDLNet_TCP_AddSocket(clc_set, cl i ent);
W tym momencie można przejść od razu do gry, czyli do funkcji GameLoop. Gdy wystąpił jakikolwiek błąd, należy spróbować jeszcze raz nawiązać połączenie z serwerem lub zakończyć działanie programu.
Gdy program pracuje jako serwer, czyli ma czekać na połączenie od klienta, obsługa połączenia sieciowego jest trudniejsza, ale zaczyna się dość podobnie:
SDLNet_ResolveHost(&ip, NULL, port) server=SDLNet_TCP_Open(&ip)
Różnica polega tylko na podaniu wartości NULL w drugim parametrze - w poprzednim przypadku podaliśmy nazwę
Listing 2. Funkcja wyświetlająca komunikaty
int DiśplayMesgCint _type)
{
SDL_Rect dst_rect;
if(msg_surface!=NULL) SDL_FreeSurface(msg_surface); if(_type==l) msg_siirface=TTF_RenderText_Blended( font, "Ustawianie czterech jednomasztowców", col_white);
// pozostdle komunikaty dst_reot.w=msg_surface->w+80; dst_rect.h=msg_surface->h; dst_rect.x=(screen->w/2) - (msg_surface->w)/2; if (_type~6)
dst_rect.y=420;
else
dst_rect.y=10;
SDL_FillRect(screen, &dst_rect, 0): SDL_BlitSurface(msg_surface,
NULL, screen, &dst_rect);
SDL_UpdateRect(screen, 0,0,0,0); return 0;
)
62
grudzień 2003