Seminarium Dyplomowe Zalety programowania prostych gier komputerowych w Javie Paweł Radulski 12-04-2013 Dlaczego Java do tworzenia gier komputerowych? Java jest jednym z wysokopoziomowych języków programistycznych, który umożliwia tworzenie dynamicznych i pełnoekranowych gier komputerowych oraz gier przeznaczonych na urządzenia mobilne jak np.: Smartfony. Java dziedziczy składnię po językach C i C++, co ułatwia opanowanie tego języka wielu programistom. Język Javy został zaprojektowany do tworzenia interaktywnych, sieciowych aplikacji. By spełnić wymagania tego typu programów w Javę wbudowano mechanizmy programowania wielowątkowego, które umozliwiają wykonywanie wielu zadań jednocześnie. Prosty mechanizm wielowątkowości i niezależność od różnych konfiguracji komputerowych przemawia za wyborem Javy do tworzenia w niej aplikacji. Inną zaletą tego języka jest pokaźna ilość "wolno-dostępnych" (ang. open-source) bibliotek ułatwiających tworzenie zarówno prostych, jak i skomplikowanych aplikacji graficznych. Nowopowstałe silniki do gier (wspierające tworzenie aplikacji trójwymiarowych) oraz popularne, zintegrowane środowiska programistyczne jak NetBeans czy Eclipse, w znacznym stopniu ułatwiają tworzenie prostych gier w tym języku. Ogólne zalety Javy W celu lepszego zrozumienia korzyści wyboru Javy do tworzenia gier komputerowych i mobilnych konieczne jest zrozumienie działania tego języka. Część z nich zostanie pokrótce opisana. WIELOPLATFORMOWOŚĆ Pojawianie się coraz to nowszych systemów operacyjnych i procesorów może przyczynić się do niepoprawnego funkcjonowania programu, który działał na starszym sprzęcie komputerowym. W celu uniknięcia tego problemu język Javy został tak zaprojektowany, by wraz z maszyną wirtualną każdy program mógł zostać poprawnie uruchomiony na dowolnym komputerze. W Javie kod wynikowy, który powstał jako efekt kompilacji jest tzw. Beta-kodem. Jest on interpretowany przez maszynę wirtualną Javy pracującą w określonym środowisku. Oznacza to, że każda aplikacja napisana w Javie jest niezależna od sprzętu i oprogramowania. OBIEKTOWOŚĆ Proces tworzenia gry komputerowej jest złożony i angażuje więcej niż jedną osobę. Podstawą do wydajnej pracy zespołu nad projektem gry jest czytelne pisanie kodu, który będzie tworzony i modyfikowany przez różnych programistów (z charakterystyczną dla nich manierą pisania programów). Obiektowo napisana aplikacja jest zawsze zamknięta w klasie, co jest pomocne w organizowaniu programu wokół zawartych w nim danych, czyli tak zwanych obiektów. Pomaga również w określeniu interfejsu dostępu do tych obiektów . Jest 1 to jeden z czynników ułatwiających tworzenie prostych w pielęgnacji systemów informatycznych, które będą optymalizowane w celu zwiększenia ich wydajności. Takie podejście jest kluczowe do tworzenia dobrze zoptymalizowanych gier, tworzonych przez zespół programistów. TWORZENIE APLIKACJI MOBILNYCH Możliwość bezproblemowego uruchomienia programów na różnych platformach oraz popularność Javy w sieci, przyczyniły się do tworzenia różnych aplikacji na urządzeniach mobilnych. Fakt, że aplikacje rozrywkowe jakimi są gry dominują wśród wszystkich tworzonych aplikacji sprawia, że Java staje się wyborem wielu programistów tworzących proste gry. ODŚMIECACZ PAMIĘCI Mechanizm ten sprawia, że w Javie nie ma konieczności jawnego usuwania obiektów i zwalniania po nich pamięci. Natomiast w językach C i C++ wymagane jest ręczne alokowanie i zwalnianie dynamicznie przydzielonej pamięci. Procedura ta może prowadzić do problemów takich jak zapominanie zwolnienia zaalokowanej wcześniej pamięci lub nieumyślne zwolnienie pamięci, która jest jeszcze używana przez inny fragment aplikacji. Java eliminuje ten problem. WIELOWĄTKOWOŚĆ Java zawiera wbudowaną obsługę programowania wielowątkowego, która powoduje asynchroniczność jej środowiska. Cecha ta pomaga zredukować brak wydajności komputera. Marnuje się mniejsza liczba cykli procesora, przez co napisane gry działają płynnie i nie dochodzi do ich wadliwego funkcjonowania. Dodatkowo, programista tworzący aplikacje w języku Java nie musi martwić się podsystemem wielozadaniowości, a jedynie odpowiednim zachowaniem programu. Fundamenty tworzenia gier komputerowych Niezależnie od stopnia złożoności gry napisanej w Javie, czy też każdym innym języku, programista lub zespół programistów musi wziąć pod uwagę sześć podstawowych czynników, które stanowią kwintesencję tworzenia gier. Są to: 1. 2. 3. 4. Wątki - podział gry na mniejsze podprogramy. Grafika i Animacja - wizualna prezentacja gry komputerowej. Interaktywność - możliwość manipulowania obiektami w świecie gry. Efekty dźwiękowe i muzyka - informowanie gracza o tym, co dzieję się na ekranie oraz zwiększenie atrakcyjności samej gry. 5. Platformy 2D/3D - tworzenie gry dwuwymiarowej lub trójwymiarowej. 6. Tryb wieloosobowy - możliwość uczestniczenia w grze przez więcej niż jedną osobę. W celu przybliżenia problematyki i zalet projektowania gier komputerowych w Javie zostaną omówione trzy pierwsze z wymienionych powyżej czynników. 2 Wątki w Javie Gra komputerowa jest przykładem programu wielowątkowego, który zazwyczaj zawiera więcej niż dwie ścieżki wykonania, działające współbieżnie. Każda z tych ścieżek stanowiących część tego programu nosi nazwę wątku. Przy tworzeniu złożonej aplikacji graficznej (jaką jest gra komputerowa), Java umożliwia pisanie własnych wątków i definiowanie ich przepływu działania. Jest to dość ważne zagadnienie, ponieważ w grze komputerowej często zachodzi potrzeba wykonywania kilku czynności jednocześnie np.: wyświetlanie obrazków, obsługa użytkownika, czy też cykliczne przesuwanie się obiektów na planszy w tym samym czasie. Do tworzenia wątków i organizowania ich zakresu i sposobu działania używa się kilku metod: METODA KLASY THREAD ZNACZENIE getName() Metoda pobiera nazwę wątku. getPriority() Metoda pobiera priorytet wątku. isAlive() Metoda sprawdza, czy wątek nadal działa. join() Czas oczekiwania na zakończenie wątku. run() Miejsce wątku. sleep() Zawieszenie działania określony czas. start() Uruchomienie wątku wywołanie metody run() . wait() Uśpienie wątku do czasu do momentu wywołania metody notify(). notify() Budzi wątek, który wywołał metodę wait() dla tego samego obiektu. rozpoczęcia wykonania wątku na przez Przykład stworzenie wątku: Thread watek = new Thread(); watek.start(); Samo stworzenie wątku nie odniesie żadnego skutku jeżeli nie zostanie przydzielone mu zadanie w metodzie run(). Wiele gotowych metod ułatwia wykorzystanie mechanizmu wielowątkowości przy pisaniu gier komputerowych w Javie. Istnieją trzy podstawowe możliwości nadania metodzie run() zadań: 1. Rozwinięcie klasy Thread. 2. Implementacja interfejsu Runnable. 3. Użycie wewnętrznych klas anonimowych. 3 Zatem kiedy i w jakich warunkach używać wątków w Javie i na co warto zwrócić uwagę przy ich stosowaniu? KIEDY UŻYWAĆ KIEDY NIE UŻYWAĆ Przy ładowaniu wielu plików z Kiedy wielowątkowość powoduje lokalnych systemów plików. asynchroniczne działanie programów. Wówczas często Przy wykonywaniu jakiejkolwiek wymagane jest wymuszenie ich komunikacji sieciowej np.: wysyłanie synchronizacji. Synchronizowanie osiągniętego wyniku przez gracza do kodu (mechanizm umożliwiający serwera. spójne wykonanie wybranego ciągu Przy wykonywaniu dużych obliczeń instrukcji) może prowadzić do wielu np.: generowanie terenów w grze. niepotrzebnych opóźnień pracy gry. Kiedy „wróg” jako postać w grze (lub jego niepełny obraz) może pojawić się w połowie operacji rysowania (tymczasowa duplikacja obiektu graficznego). Kiedy efekt zakleszczenia (ang. deadlock) może być odpowiedzialny za nierówny stan pracy gry. Grafika i Animacja Wyróżnia się trzy typy graficzne gier w Javie: 1. Gra apletowa - głównie zastosowana w przeglądarkach internetowych. Charakterystyką tego typu gier jest to, że nie jest grą złożoną i gracz nie może wykonać pewnych podstawowych czynności jak np. zapisać swój stan gry. 2. Gra okienkowa - aplikacja, która jest widoczna w okienku z wszystkimi elementami interfejsu pulpitu jak również elementami okienka, np.: pasek tytułu, pasek menu. 3. Gra pełnoekranowa -gracz ma pełną kontrolę nad jej wizualną prezentacją. Gra która jest pozbawiona zbędnych elementów interfejsu pulpitu użytkownika. Trzy obiekty potrzebne do przejścia w tryb graficzny pełnoekranowy: 1. Obiekt klasy Window – stanowi swego rodzaju "płótno", na którym powstaje graficzna część gry. Tworzy najwyższy poziom klasy okna, które działa bezpośrednio na pulpicie. 2. Obiekt klasy DisplayMode – jest odpowiedzialny za rozdzielczość, głębię bitową i tempo odświeżania ekranu. 3. Obiekt klasy GraphicsDevice – jest odpowiedzialny za zmianę trybu wyświetlania oraz wgląd na właściwości wyświetlania. Pełni on rolę Interfejsu do karty graficznej. 4 Obrazy podlegające akceleracji sprzętowej są zazwyczaj przechowywane w pamięci karty graficznej, rzadziej w pamięci systemu. Java automatycznie stara się wykorzystać akcelerację sprzętową grafiki poprzez zestaw dostępnych narzędzi np.: getImage(). Możliwość „przyśpieszenia” przetwarzania obrazu zależy zarówno od systemu operacyjnego, jak typu grafiki. W Javie można „wymusić”, by dana grafika znajdowała się w pamięci karty graficznej poprzez użycie „niestabilnych obrazów” (ang. VolatileImages). W sytuacji gdy dana grafika nie może zostać obsłużona przez kartę graficzną Java generuję odpowiedni komunikat informujący osobę programującą. Przykład: createVolatileImage(int w, int h) - użycie metody Component createCompatibleVolatileImage(int w, int h) – użycie metody GraphicConfiguration W kwestii tworzenia animacji w grze, programista zawsze powinien przewidzieć rozwiązanie, które będzie najwydajniejsze z jak najmniejszym obciążeniem zasobów komputera. Przy tworzeniu prostych gier komputerowych można wykorzystać dwie metody do wyświetlania obrazu. Pierwsza to Double buffer, która zapewnia poprzez kartę graficzną płynne wyświetlanie kolejnych obrazów, a każda kolejna klatka jest już wcześniej tworzona w jej pamięci. Druga metoda to Page flipping. W metodzie tej wykorzystywane są wskaźniki karty graficznej, które są jej adresem w pamięci. Wskaźnik informuje kartę graficzną gdzie należy szukać treść graficzną i gdzie ona ma być odświeżana w następnym cyklu odświeżania. W Javie można również wykorzystać gotową już klasę BufferStrategy(), która sprawdza możliwości sprzętu komputerowego i wykorzystuje najwydajniejszą metodę do wyświetlania obrazu na monitorze. Interaktywność Zadaniem interaktywności jest odbiór informacji i reagowanie na nią. Za prosty przykład w grze komputerowej może posłużyć obiekt w postaci trójkąta, będący imitacją np. statku kosmicznego, którym można poruszać się w dowolną stronę po wciśnięciu odpowiedniego klawisza. Podstawowym pośrednikiem pomiędzy grą komputerową, a graczem jest klawiatura i myszka. Przy tworzeniu interaktywności w prostych grach napisanych w Javie, może posłużyć standardowy zestaw narzędzi modelu zdarzeń Abstract Window Toolkit. AWT to pakiet zawierający niezależny od platformy systemowej zestaw klas do projektowania aplikacji w środowisku graficznym jakim jest np.: gra. Jednym z podstawowych interfejsów jest interfejs KeyListener(). Definiuje on trzy metody. Metody keyPressed() i keyReleased() są wywoływane w momencie, w którym klawisz jest odpowiednio naciskany i zwalniany. Metoda keyTyped () jest wywoływana wtedy, gdy na klawiaturze wpisano znak. Brak interaktywności w grze można porównać do gry w szachy, gdzie pionki zostały przyklejone do szachownicy, co w rezultacie uniemożliwia wykonywanie jakiegokolwiek ruchu przez gracza. 5 Podsumowanie Pisanie gier komputerowych jest złożonym procesem, który zazwyczaj angażuje zespół ludzi z różnymi kwalifikacjami. Języki programowania trzeciej generacji, znacznie ułatwiają pracę przy tworzeniu gier komputerowych. W przypadku Javy, możliwości jakie oferują bogate biblioteki z pokaźnym zestawem narzędzi, znacznie ułatwiają pracę programisty. 6