Programowanie gier

symulator lotu FlightGear zaprogramowany w OpenGL przy użyciu języka C++

Programowanie gier – specyficzna dziedzina pracy programistów. Łączy inżynierię oprogramowania, grafikę i multimedia, sztuczną inteligencję, fizykę, matematykę, optymalizację, algorytmikę i wiele innych dziedzin w jednym wspólnym celu. Wymaga współpracy z wieloma specjalistami z innych dziedzin, między innymi grafikami, muzykami, autorami tekstów.

Powstało wiele bibliotek, które wspomagają proces programowania gier, jedne z nich są przeznaczone dla początkujących programistów, jak na przykład Allegro czy SDL, inne przeznaczone są dla bardziej zaawansowanych (OpenGL). Istnieją biblioteki poświęcone tylko jednemu zagadnieniu, np. grafice (OpenGL) czy dźwiękowi (OpenAL, FMOD, BASS), inne natomiast są bardzo rozbudowane i zapewniają kompleksowe mechanizmy umożliwiające programiście skupienie się na samym pisaniu gier zamiast zmuszać go do spędzania czasu na rozwiązywaniu problemów technicznych (DirectX).

Grafika[edytuj | edytuj kod]

W bardziej rozbudowanych grach komputerowych za przetwarzanie grafiki odpowiada tzw. silnik graficzny. Można go podzielić na dwa podstawowe rodzaje: silnik 2D i silnik 3D. W niektórych przypadkach silnik 2D może prezentować ładniejszą grafikę niż silnik 3D, jednak wraz ze wzrostem możliwości kart graficznych w dziedzinie przetwarzania grafiki silnik 2D wychodzi z użycia. Ponadto aktualne możliwości techniczne sprawiają, że pisanie dedykowanych silników 2D wychodzi z użycia, w wielu przypadkach dużo lepszym rozwiązaniem wydaje się zaangażowanie podsystemu grafiki 3D do generowania grafiki dwuwymiarowej – osiąga się to poprzez ustawienie specjalnego trybu rzutowania zwanego ortogonalnym, oraz renderowanie na ekranie prostokątów z nałożonymi teksturami.

Silnik 2D[edytuj | edytuj kod]

Silnik 2D tworzy scenę w grze zazwyczaj poprzez nakładanie gotowych dwuwymiarowych obrazów w odpowiedniej kolejności. Czasem są one jeszcze modyfikowane, np. poprzez zmianę jasności, kolor-keying (maskowanie barw) albo przeźroczystości. Elementy sceny mogły zostać stworzone przez twórców poprzez wyrenderowanie obiektów trójwymiarowych.

Silnik 2D to taki, który przetwarza jedynie grafikę dwuwymiarową, jednak zazwyczaj twórcom gier zależy, by utworzona w ten sposób scena sprawiała wrażenie trójwymiarowej. Większość silników 2D wykorzystuje rzut izometryczny. Świat w ten sposób przedstawiony prezentuje się ładnie, często bardziej szczegółowo niż w przypadku grafiki 3D. Podstawową wadą tego typu wyświetlania grafiki jest brak perspektywy (obiekty, które w świecie gry mają sprawiać wrażenie bardziej oddalonych, są tej samej wielkości co obiekty bliższe).

Silniki 2D są zazwyczaj proste w tworzeniu. Głównymi problemami podczas ich tworzenia jest określenie miejsca wyświetlania poszczególnych elementów sceny oraz kolejności ich wyświetlania. Łatwo jest również z góry określić, które elementy sceny nie są widoczne, bo np. znajdują się poza ekranem. Powoduje to, że optymalizacje silników 2D są proste. Podstawową wadą jest brak możliwości swobodnego obracania kamery w grze. Dotychczas silniki 2D były bardzo popularne w grach strategicznych, jednak wraz ze wzrostem jakości grafiki 3D zaprzestaje się tworzenia gier 2D.

Silnik 3D[edytuj | edytuj kod]

Silnik 3D ma na celu przygotowanie oraz wyrenderowanie sceny 3D. Grafika oparta na silniku 3D jest bardzo atrakcyjna dla gracza, jednak stworzenie dobrego silnika 3D jest niezwykle trudnym i pracochłonnym zajęciem. Sam rendering jest procesem tak skomplikowanym, że wszystkie tworzone obecnie gry wykorzystują gotowe biblioteki, jak np. DirectX czy OpenGL. Dzięki temu programista nie musi tworzyć kodu odpowiedzialnego za sam rendering oraz nie musi zagłębiać się w szczegóły działania kart graficznych.

Podstawowymi elementami, z których tworzony jest świat gry, są obiekty trójwymiarowe, zazwyczaj tworzone w programach takich jak 3D Studio, oraz tekstury nakładane na te obiekty. Oprócz tego we współczesnych grach występują różne efekty, jak np. światła, odblaski, cieniowanie, cząsteczki. Efekty te wpływają na realizm grafiki oraz na prędkość tworzenia poszczególnych klatek sceny. Z upływem lat w grach komputerowych efektów jest coraz więcej, co sprawia, że utworzenie silnika 3D staje się procesem coraz bardziej pracochłonnym. Tworzenie takich efektów jak kurz, falowanie wody, refleksy świetlne, pochłania sporo pracy. Wymaga również wprowadzania coraz bardziej zaawansowanych technologii do kart graficznych, jak np. Vertex Shader i Pixel Shader.

Ograniczona prędkość przetwarzania grafiki sprawia, że twórcy gier poświęcają dużo czasu na optymalizację silników 3D. Jest to zagadnienie bardzo obszerne, np. jednym z najistotniejszym elementów optymalizacji jest określenie z góry, które elementy świata gry nie będą widoczne. Trudno jest określić np. czy dom, na który patrzymy, na pewno zasłania w całości dom znajdujący się dalej. W przypadku gier, w których gracz porusza się po pomieszczeniach przechodząc z pokoi do pokoi, określa się je jako odseparowane elementy. Wszelkie miejsca, przez które jeden pokój może być widziany z innego pokoju, określa się mianem portali. Dzięki temu, jeśli gracz znajduje się w którymś z pokoi, można pominąć wyświetlanie innych pokoi, chyba że w zasięgu kamery znajduje się portal. Ten sposób optymalizacji ma ogromny wpływ na szybkość działania gry. Jednym z prostszych sposobów optymalizacji, dzięki któremu można zredukować ilość wyświetlanych elementów, jest mgła.

Kolejną optymalizacją jest tworzenie tekstur o różnych wielkościach i nakładanie ich w zależności od odległości od kamery. Czasem stosuje się również obiekty o różnej liczbie wielokątów w zależności od odległości od kamery (Level of detail). O ile przeskalowanie tekstur jest proste, o tyle zmniejszenie ilości wielokątów w obiekcie 3D przy zachowaniu podobnego wyglądu z nałożoną teksturą jest bardzo trudne. W silnikach 3D stosuje się jeszcze cały szereg innych optymalizacji, jak np. renderowanie niektórych elementów sceny rzadziej niż przy każdej następnej klatce itp.

Ciągły wzrost wydajności kart graficznych oraz nowe jednostki i funkcje sprawiają, że silnik 3D szybko staje się przestarzały. Jednocześnie nakłady pracy podczas tworzenia nowego silnika są ogromne. Powoduje to, że większość gier korzysta z silników 3D innych producentów, zwłaszcza że są one dosyć uniwersalne i można je stosować w różnych grach (w przeciwieństwie do systemu sztucznej inteligencji).

Rozwiązania nietypowe[edytuj | edytuj kod]

Czasem stosuje się rozwiązania na pograniczu silnika 3D, próbując osiągnąć zadowalającą grafikę niskim kosztem i jednocześnie szybko działającą. Takie rozwiązania można znaleźć np. w grach GTA 2 oraz Diablo 2. W Diablo 2 umożliwiło to wykorzystanie tych samych grafik co w trybie 2D, jednak dzięki zastosowaniu renderingu możliwe było uzyskanie perspektywy. Rozwiązanie wykorzystane w grze polegało na tym, że w scenie 3D zamiast pełnych, trójwymiarowych obiektów w odpowiednich miejscach wyświetlane były dwuwymiarowe grafiki 2D zwrócone w stronę kamery. Jednak takie rozwiązanie sprawiało, że nie było możliwości obracania kamery. Gdyby była taka możliwość, całe „oszustwo” wyszłoby na jaw i gracz zauważyłby, że wszystkie obiekty w grze są tak naprawdę płaskie.

Dźwięk[edytuj | edytuj kod]

W przeciwieństwie do grafiki, dźwięk nie jest niezbędnym elementem gry, jednak wszystkie nowoczesne gry generują dźwięki. W większości gier w tle gra muzyka. Ma ona na celu wytworzenie klimatu i jest uzależniona od rodzaju gry. Dawniej stosowało się dźwięki z głośniczka systemowego, później MIDI, jednak w obecnych grach korzysta się częściej z innych formatów jak np. MP3/OGG. Utworzenie odpowiednich kompozycji zleca się zazwyczaj zewnętrznym firmom, zespołom lub orkiestrom. W wielu grach muzyka zależy od tego, co aktualnie dzieje się w grze.

Poza muzyką w grze występują często teksty mówione, co wymusza nagranie odpowiednich tekstów. Czasami na taką współpracę decydują się znani aktorzy, np. Cezary Pazura. Oprócz tego w grze występuje wiele krótkich dźwięków, jak np. stąpnięcie po ziemi, przeładowanie broni itp. Tego typu dźwięki bywają często nagrane w formacie WAV.

Gra może obsługiwać dźwięki mono, stereo lub wielokanałowe. W zależności od tego, gdzie oraz w jakiej odległości dany dźwięk się pojawi, gracz usłyszy go z odpowiedniej strony i odpowiednio głośno. By nadać realizmu grze stosuje się czasem różne inne efekty (np. niektóre gry samochodowe symulują efekt Dopplera). Pomimo tego dźwięk jest jednym z prostszych zagadnień pojawiających się podczas tworzenia gier.

Sztuczna inteligencja[edytuj | edytuj kod]

W grach komputerowych często występują postacie kierowane przez sam komputer. Zazwyczaj zamierzeniem autorów jest, by zachowanie takich postaci przypominało w możliwie jak największym stopniu zachowanie ludzkie. Ponadto algorytmy sztucznej inteligencji są ściśle uzależnione od rodzaju gry. Są zupełnie inne w przypadku gier samochodowych, gier typu FPS, czy gier strategicznych. W większości tych gier pojawia się zagadnienie przemieszczania bota (czyli postaci kierowanej przez komputer) po świecie gry. Służą do tego specjalnie określone punkty w świecie oraz algorytmy wyszukiwania drogi, np. AStar. Zagadnienia związane z ruchem są obszerne i zależą w dużej mierze od rodzaju gry.

Zarządzanie zasobami[edytuj | edytuj kod]

Współczesne gry wykorzystują ogromne ilości dodatkowych danych, takich jak tekstury, pliki dźwiękowe i muzyczne, pliki poziomów, modele postaci, pliki konfiguracyjne i skryptowe itp. Wielkość tych zasobów często liczy się w setkach megabajtów, logiczne jest więc, że przechowywanie ich wszystkich jednocześnie w pamięci jest niemożliwe. Dlatego kolejnym ważnym aspektem programowania gier jest zaprojektowanie elastycznego, uniwersalnego i wydajnego zarządcy zasobów, który zautomatyzuje wczytywanie, zarządzanie priorytetami, używanie, zwalnianie i obsługę błędów wszystkich zasobów używanych przez grę.

Wiele gier komputerowych nie przechowuje swoich plików danych bezpośrednio na dysku, lecz stosuje technikę zwaną wirtualnym systemem plików, która polega na tym, że pliki zasobów są łączone w jeden wielki plik, z którego potrzebne zasoby są odczytywane na żądanie. Dzięki temu dużo trudniejsze staje się nielegalne użycie zasobów przez osoby trzecie, poza tym można stosować inne techniki, np. kompresowanie czy szyfrowanie.

Pętla gry[edytuj | edytuj kod]

Właściwie cała gra działa na podstawie jednej pętli – pętli gry. W niej są wywoływane kolejno warstwy wejścia, logiki, grafiki oraz dźwięku.

Najczęstsza kolejność poleceń w pętli:

pętla( użytkownik nie wyłączył gry )   sprawdzenie wejścia gry   wykonanie warstwy logicznej   sprawdzenie kolizji   narysowanie grafiki   odegranie dźwięków koniec pętli

Warstwowa budowa[edytuj | edytuj kod]

Gra zazwyczaj jest zbudowana z warstw: grafiki, logiki, wejścia, dźwięku. Każda z warstw przechowuje ważne tylko dla siebie dane – przykładowo warstwa wejścia stan wciśnięcia klawisza myszki – oraz odpowiednio na nie reaguje. W grze zazwyczaj występuje szeroko pojęta komunikacja między wszystkimi warstwami. Idąc dalej tym samym przykładem warstwa wejścia otrzymała komunikat, że gracz przycisnął lewą strzałkę na klawiaturze. W związku z tym, warstwa wejścia wywołuje warstwę logiczną, aby ta odpowiedziała – i warstwa logiki przesuwa pozycję gracza o n pikseli w lewo. Natomiast procedura rysująca z warstwy graficznej, chce narysować gracza, więc odwołuje się do warstwy logiki, aby ta zwróciła pozycję gracza – aby móc narysować go na ekranie według jego pozycji. Każda z warstw ma swoją funkcję, w której jest jej pętla, czyli na przykład rysowanie grafiki w warstwie graficznej. W pętli gry wszystkie pętle warstw są wywoływane według wyżej podanej kolejności.

Zobacz też[edytuj | edytuj kod]