Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: [email protected]
PRZYK£ADOWY ROZDZIA£PRZYK£ADOWY ROZDZIA£
IDZ DOIDZ DO
ZAMÓW DRUKOWANY KATALOGZAMÓW DRUKOWANY KATALOG
KATALOG KSI¥¯EKKATALOG KSI¥¯EK
TWÓJ KOSZYKTWÓJ KOSZYK
CENNIK I INFORMACJECENNIK I INFORMACJE
ZAMÓW INFORMACJEO NOWO�CIACH
ZAMÓW INFORMACJEO NOWO�CIACH
ZAMÓW CENNIKZAMÓW CENNIK
CZYTELNIACZYTELNIA
FRAGMENTY KSI¥¯EK ONLINEFRAGMENTY KSI¥¯EK ONLINE
SPIS TRE�CISPIS TRE�CI
DODAJ DO KOSZYKADODAJ DO KOSZYKA
KATALOG ONLINEKATALOG ONLINE
Java. Tworzenie gier
Wykorzystaj do tworzenia gier
najpopularniejszy jêzyk programowania ery internetu
Java jest nowoczesnym i prostym jêzykiem programowania zorientowanym obiektowo.
Trudno nie doceniaæ jej zalet — czytelna i zrozumia³a sk³adnia, uniwersalny, niezale¿ny
od platformy kod i przede wszystkich bezp³atny dostêp do doskona³ych narzêdzi
programistycznych. Javê doceni³o ju¿ wielu twórców oprogramowania, w�ród których
brakowa³o jednak twórców gier i aplikacji „rozrywkowych”. Dotychczas w Javie
tworzono jedynie proste uk³adanki, gry karciane i ³amig³ówki lub nie�miertelne aplety
typu „padaj¹cy �nieg”, które przez d³ugi czas straszy³y nas z przegl¹darek
internetowych. Czas na zmianê! Wykorzystaj swoje umiejêtno�ci programowania
w Javie, siêgnij po wiadomo�ci zawarte w tej ksi¹¿ce i napisz prawdziw¹ grê —
z grafik¹, inteligentnymi przeciwnikami, wydajnym silnikiem 3D wspomaganym
sprzêtowo i przestrzennym d�wiêkiem.
„Java. Tworzenie gier” to ksi¹¿ka o programowaniu gier, na jak¹ czeka³e�. Zawiera
zarówno opis podstawowych mechanizmów u¿ywanych w grach, jak i szczegó³owe
omówienie zaawansowanych technik. Dowiesz siê, jak wykorzystaæ platformê Java 1.4
do tworzenia szybkich, pe³noekranowych gier akcji, przygodówek i trójwymiarowych
strzelanek. Nauczysz siê tworzyæ wspomagan¹ sprzêtowo grafikê, algorytmy sztucznej
inteligencji i znajdowania drogi, realistyczne efekty d�wiêkowe i mechanizmy obs³ugi
gry dla wielu graczy.
• Algorytmy wy�wietlania grafiki 2D
• Tworzenie interfejsu u¿ytkownika z wykorzystaniem komponentów Swing
• Programowanie efektów d�wiêkowych dzia³aj¹cych w czasie rzeczywistym
• Klient i serwer gry wieloosobowej
• Wy�wietlanie grafiki 3D
• Mapowanie tekstur i symulacja o�wietlenia
• Drzewa BSP
• Algorytmy detekcji kolizji i wykrywania drogi
• Sztuczna inteligencja i tworzenie botów
• Zapisywanie stanu gry
• Optymalizacja kodu
• System sterowania gr¹
Udowodnij „fachowcom” krytykuj¹cym szybko�æ Javy, ¿e nie maj¹ racji.
Napisz wspania³¹ grê w Javie. W tej ksi¹¿ce znajdziesz wszystkie wiadomo�ci,
które s¹ do tego niezbêdne.
Autorzy: David Brackeen, Bret Barker, Laurence Vanhelsuwe
T³umaczenie: S³awomir Dzieniszewski (rozdz. 7, 8, 12),
Pawe³ Gonera (rozdz. 1 – 6, 14 – 16), Miko³aj
Szczepaniak (rozdz. 9 – 11, 13, 17 – 19)
ISBN: 83-7361-411-7
Tytu³ orygina³u: Developing Games in Java
Format: B5, stron: 756
Przyk³ady na ftp: 4924 kB
Spis treści
O Autorze ........................................................................................ 15
Wstęp ............................................................................................. 17
Część I Podstawy gier w języku Java ..........................................25
Rozdział 1. Wątki w języku Java ........................................................................ 27Co to jest wątek? ...............................................................................................................28Tworzenie i uruchamianie wątków w języku Java............................................................28
Rozszerzanie klasy Thread .........................................................................................29Implementacja interfejsu Runnable ............................................................................29Użycie anonimowej klasy wewnętrznej......................................................................29Oczekiwanie na zakończenie wątku ...........................................................................30Uśpione wątki .............................................................................................................30
Synchronizacja ..................................................................................................................30Po co nam synchronizacja?.........................................................................................30Jak synchronizować? ..................................................................................................31Kiedy należy synchronizować?...................................................................................32Kiedy nie synchronizować? ........................................................................................33Unikanie zakleszczeń..................................................................................................33
Użycie wait() oraz notify()................................................................................................34Model zdarzeń Javy...........................................................................................................35Kiedy używać wątków? ....................................................................................................36Kiedy nie używać wątków?...............................................................................................36Podsumowanie: pule wątków............................................................................................36Podsumowanie ..................................................................................................................41
Rozdział 2. Grafika 2D oraz animacja ................................................................. 43Grafika pełnoekranowa .....................................................................................................44
Układ ekranu...............................................................................................................44Kolor piksela i głębia koloru.......................................................................................45Częstotliwość odświeżania .........................................................................................46Przełączanie do trybu pełnoekranowego ....................................................................46Anti-aliasing................................................................................................................50Który tryb graficzny należy zastosować? ...................................................................51
Rysunki..............................................................................................................................52Przezroczystość...........................................................................................................52Formaty plików...........................................................................................................52Odczytywanie rysunków.............................................................................................53
6 Java. Tworzenie gier
Rysunki przyspieszane sprzętowo ..............................................................................56Program testujący wydajność rysowania rysunków ...................................................58Animacja .....................................................................................................................61Renderowanie aktywne...............................................................................................64Pętla animacji..............................................................................................................64
Usuwanie migotania i szarpania........................................................................................67Podwójne buforowanie ...............................................................................................67Przełączanie stron .......................................................................................................68Odświeżanie monitora i szarpanie ..............................................................................70Klasa BufferStrategy...................................................................................................70Tworzenie zarządcy ekranów .....................................................................................71Duszki .........................................................................................................................78
Proste efekty......................................................................................................................84Przekształcenia rysunków...........................................................................................84
Podsumowanie ..................................................................................................................89
Rozdział 3. Interaktywność i interfejs użytkownika ............................................. 91Model zdarzeń AWT.........................................................................................................94Zdarzenia klawiatury.........................................................................................................95Zdarzenia myszy ...............................................................................................................99Przesuwanie myszy metodą „rozglądania się”................................................................103
Ukrywanie wskaźnika myszy ...................................................................................107Tworzenie klasy InputManager.......................................................................................108Zastosowanie obiektu InputManager ..............................................................................119
Zatrzymywanie gry ...................................................................................................119Dodajemy grawitację ................................................................................................120
Projektowanie intuicyjnych interfejsów użytkownika ....................................................125Wskazówki do projektu interfejsu użytkownika.......................................................126
Wykorzystanie komponentów Swing..............................................................................127Podstawy Swing........................................................................................................127Stosowanie Swing w trybie pełnoekranowym..........................................................128
Tworzenie prostego menu ...............................................................................................130Konfiguracja klawiatury przez użytkownika ..................................................................135Podsumowanie ................................................................................................................141
Rozdział 4. Efekty dźwiękowe oraz muzyka....................................................... 143Podstawy dźwięku...........................................................................................................144API Java Sound ...............................................................................................................144
Otwieranie pliku dźwiękowego ................................................................................145Zastosowanie interfejsu Line ....................................................................................145
Odtwarzanie dźwięków...................................................................................................146Tworzenie architektury filtrów działających w czasie rzeczywistym.............................151Tworzenie filtra „echo”, działającego w czasie rzeczywistym .......................................155Emulacja dźwięku 3D .....................................................................................................159
Mechanizmy potrzebne do tworzenia filtra 3D ........................................................160Implementacja filtra 3D ............................................................................................161Testowanie filtra 3D .................................................................................................163
Tworzenie obiektu zarządzającego dźwiękiem...............................................................167Klasa Sound ..............................................................................................................167Klasa SoundManager ................................................................................................168Zmienne lokalne dla wątków....................................................................................175
Odtwarzanie muzyki .......................................................................................................176Odtwarzanie dźwięku CD.........................................................................................177Odtwarzanie plików MP3 i Ogg Vorbis ...................................................................177
Spis treści 7
Odtwarzanie muzyki MIDI .......................................................................................178Tworzenie muzyki adaptacyjnej ...............................................................................182
Podsumowanie ................................................................................................................184
Rozdział 5. Tworzenie dwuwymiarowej gry platformowej ................................... 185Tworzenie mapy złożonej z kafelków.............................................................................186
Implementacja mapy korzystającej z kafelków ........................................................187Ładowanie mapy złożonej z kafelków......................................................................190Rysowanie mapy złożonej z kafelków......................................................................193Rysowanie duszków..................................................................................................195Przewijanie z paralaksą.............................................................................................195Premie .......................................................................................................................197Proste obiekty wrogów .............................................................................................200
Wykrywanie kolizji .........................................................................................................207Detekcja kolizji .........................................................................................................207Obsługa kolizji ..........................................................................................................208Kolizje duszków........................................................................................................212
Dokończenie i przyspieszanie gry...................................................................................213Tworzenie wykonywalnego pliku .jar.............................................................................213Pomysły na rozszerzenie gry...........................................................................................215Podsumowanie ................................................................................................................216
Rozdział 6. Gry wieloosobowe.......................................................................... 217Rewolucja w bibliotekach wejścia-wyjścia w języku Java.............................................219
Przegląd bibliotek NIO z JDK 1.4 ............................................................................220Kanały .......................................................................................................................220Bufory .......................................................................................................................223Selektory oraz klasy SelectionKey ...........................................................................226
ChatterBox, prosta aplikacja dla wielu użytkowników...................................................227Serwer: ChatterServer ...............................................................................................227Kompilowanie i uruchamianie serwera ....................................................................233Klient: ChatterClient .................................................................................................235Kompilowanie i uruchamianie klienta ......................................................................236
Szkielet serwera gry wieloosobowej ...............................................................................237Cele projektu i taktyka ..............................................................................................237Projekt .......................................................................................................................238Wspólne klasy i interfejsy.........................................................................................242Implementacja serwera .............................................................................................244Klient.........................................................................................................................252
Przykładowa gra: RPS (kamień, papier, nożyczki).........................................................253Klasy .........................................................................................................................253Uruchamianie gry RPS .............................................................................................256
Wykończanie gry: rozbudowa szkieletu .........................................................................258Interfejs klienta .........................................................................................................258Trwałość....................................................................................................................258Listy znajomych, pokoje i czat .................................................................................258
Administracja serwera.....................................................................................................259Rejestracja zdarzeń ...................................................................................................259Uruchamianie i wyłączanie.......................................................................................260Konsole administracyjne serwera .............................................................................261Śledzenie gry.............................................................................................................261
Zagadnienia zaawansowane ............................................................................................262Rozłączenia i ponowne połączenia ...........................................................................262Tunelowanie HTTP...................................................................................................263
8 Java. Tworzenie gier
Testowanie za pomocą botów...................................................................................265Te nieznośne modemy ..............................................................................................266Profilowanie i tworzenie statystyk wydajności.........................................................266Dostrajanie wydajności .............................................................................................268
Podsumowanie ................................................................................................................270
Część II Grafika trójwymiarowai zaawansowane techniki programowania gier ...............271
Rozdział 7. Grafika trójwymiarowa ................................................................... 273Typy renderowania grafiki trójwymiarowej ...................................................................274Nie zapominajmy o matematyce .....................................................................................275
Trygonometria i trójkąty prostokątne .......................................................................276Wektory.....................................................................................................................276
Podstawy grafiki trójwymiarowej ...................................................................................281Algebra trzech wymiarów ...............................................................................................284Wielokąty ........................................................................................................................289Przekształcenia przestrzeni trójwymiarowej...................................................................292
Rotacje ......................................................................................................................293Hermetyzacja przekształceń rotacji i translacji.........................................................295Stosowanie transformacji..........................................................................................298Porządek rotacji ........................................................................................................300
Prosty potok tworzenia grafiki 3D ..................................................................................301Ruch kamery ...................................................................................................................305Bryły i usuwanie niewidocznych powierzchni................................................................305
Iloczyn skalarny wektorów.......................................................................................307Iloczyn wektorowy wektorów...................................................................................308Dodatkowe właściwości iloczynu skalarnego i wektorowego..................................311
Rysowanie wielokątów za pomocą konwertera skanującego .........................................312Optymalizowanie konwertera skanującego za pomocą liczb stałoprzecinkowych ..317
Przycinanie w trzech wymiarach.....................................................................................321Ostateczny potok renderowania ......................................................................................324Podsumowanie ................................................................................................................332
Rozdział 8. Mapowanie tekstur i oświetlenie.................................................... 333Podstawy mapowania tekstur uwzględniającego perspektywę.......................................334
Wyprowadzenie równań wykorzystywanych do mapowania tekstur .......................335Prosty mechanizm mapowania tekstur............................................................................340
Wady naszego prostego mechanizmu renderującego ...............................................347Optymalizowanie mapowania tekstur .............................................................................348
Przechowywanie tekstur ...........................................................................................349Prosta optymalizacja .................................................................................................352Rozwijanie metod w miejscu wywołania .................................................................356Przykładowy program korzystający z szybkiego mapowania tekstur ......................358
Prosty mechanizm generowania oświetlenia...................................................................359Odbicie rozproszone .................................................................................................359Światło otoczenia ......................................................................................................360Uwzględnianie intensywności światła pochodzącego ze źródła światła ..................360Spadek intensywności światła wraz z odległością....................................................360Implementowanie punktowego źródła światła..........................................................361
Implementowanie oświetlania tekstur.............................................................................362Tworzenie zaawansowanych trików oświetleniowych za pomocą map cieniowania.....369
Odnajdywanie prostokąta ograniczającego...............................................................369Stosowanie mapy cieniowania..................................................................................371
Spis treści 9
Budowanie mapy cieniowania ..................................................................................373Budowanie powierzchni............................................................................................375Przechowywanie powierzchni w pamięci podręcznej ..............................................378Przykład z cieniowaniem powierzchni .....................................................................384
Dodatkowe pomysły........................................................................................................385Sugerowanie głębi.....................................................................................................385Fałszywe cienie.........................................................................................................386Mapowanie MIP........................................................................................................386Interpolacja dwuliniowa............................................................................................386Interpolacja trójliniowa.............................................................................................387Mapy wektorów normalnych i mapy głębokości......................................................387Inne typy oświetlenia ................................................................................................388
Podsumowanie ................................................................................................................388
Rozdział 9. Obiekty trójwymiarowe................................................................... 389Usuwanie ukrytych powierzchni.....................................................................................390
Algorytm malarza .....................................................................................................390Odwrotny algorytm malarza .....................................................................................391Z-bufor ......................................................................................................................391Z-bufor z wartościami 1/z.........................................................................................393Obliczanie z-głębokości............................................................................................396
Animacja trójwymiarowa................................................................................................397Ruch postępowy........................................................................................................400Ruch obrotowy..........................................................................................................402
Grupy wielokątów...........................................................................................................407Iteracyjna obsługa wszystkich wielokątów należących do grupy.............................411
Wczytywanie grup wielokątów z pliku OBJ...................................................................413Format pliku OBJ......................................................................................................414Format pliku MTL ....................................................................................................420
Obiekty w grze ................................................................................................................421Zarządzanie obiektami w grze.........................................................................................425Łączenie elementów........................................................................................................427Możliwe rozszerzenia w przyszłości...............................................................................433Podsumowanie ................................................................................................................434
Rozdział 10. Zarządzanie sceną trójwymiarową za pomocą drzew BSP ................ 435Wprowadzenie do drzew BSP.........................................................................................436Podstawy drzew binarnych..............................................................................................437Jednowymiarowe drzewo BSP........................................................................................440Dwuwymiarowe drzewo BSP .........................................................................................442
Przykład budowy drzewa BSP..................................................................................443Przykład przeglądania drzewa BSP ..........................................................................447
Implementacja dwuwymiarowego drzewa BSP..............................................................448Linia podziału BSP ...................................................................................................450Wyznaczanie położenia punktu względem linii .......................................................450Dwójkowy podział wielokąta ...................................................................................454Przeglądanie drzewa BSP .........................................................................................455Przeglądanie poprzeczne...........................................................................................457Przeglądanie od przodu do tyłu.................................................................................458Budowa drzewa.........................................................................................................459Znajdowanie punktu przecięcia dwóch prostych......................................................463Przycinanie wielokątów do linii................................................................................465Usuwanie pustych przestrzeni T-złączy....................................................................467Testowanie drzewa BSP ...........................................................................................469
10 Java. Tworzenie gier
Rysowanie wielokątów od przodu do tyłu ......................................................................471Pierwszy przykład wykorzystania drzewa BSP ..............................................................479Rysowanie obiektów na scenie .......................................................................................480Wczytywanie map z pliku ...............................................................................................482Łączenie elementów........................................................................................................486Rozszerzenia....................................................................................................................486Podsumowanie ................................................................................................................488
Rozdział 11. Wykrywanie kolizji ......................................................................... 489Podstawy kolizji ..............................................................................................................490Kolizje typu obiekt-obiekt...............................................................................................491
Eliminowanie testów.................................................................................................491Sfery otaczające ........................................................................................................493Walce otaczające.......................................................................................................495Problem przetwarzania dyskretno-czasowego..........................................................498
Kolizje typu obiekt-świat ................................................................................................499Prostopadłościany otaczające, wykorzystywane do wykrywania kolizjiz podłogami ............................................................................................................499
Znajdowanie liścia drzewa BSP dla danego położenia.............................................500Implementacja testów wysokości podłogi i sufitu ....................................................501Prostopadłościany otaczające, wykorzystywane do testowania kolizji ze ścianami .. 503Punkt przecięcia z odcinkiem wielokąta reprezentowanego w drzewie BSP...........504Problem narożników .................................................................................................508Implementacja wykrywania kolizji typu obiekt-świat ..............................................509
Prosty program demonstracyjny wykrywający kolizje ...................................................511Obsługa kolizji z przesuwaniem .....................................................................................512
Przesuwanie obiektu wzdłuż innego obiektu............................................................512Przesuwanie obiektu wzdłuż ściany..........................................................................515Grawitacja i płynny ruch na schodach (przesuwanie obiektu wzdłuż podłogi)........517Skakanie....................................................................................................................520
Program demonstracyjny obsługujący kolizje z przesuwaniem .....................................521Rozszerzenia....................................................................................................................522Podsumowanie ................................................................................................................522
Rozdział 12. Odnajdywanie drogi w grze............................................................. 523Podstawowa wiedza na temat technik odnajdywania drogi ............................................524Pierwsze przymiarki do odnajdywania drogi w grze ......................................................524
Przeszukiwanie wszerz .............................................................................................527Podstawy algorytmu A*..................................................................................................530Stosowanie algorytmu A* w grze ...................................................................................535Algorytm A* w połączeniu z drzewami BSP..................................................................536
Przejścia ....................................................................................................................536Implementowanie portali ..........................................................................................537
Uniwersalny mechanizm odnajdywania drogi ................................................................541Przygotowywanie robota PathBot...................................................................................545Sposoby ulepszania przeszukiwania A* .........................................................................549Podsumowanie ................................................................................................................550
Rozdział 13. Sztuczna inteligencja ..................................................................... 551Podstawy sztucznej inteligencji ......................................................................................552Pozbawianie botów ich boskiej mocy .............................................................................553
„Widzenie”................................................................................................................554„Słyszenie”................................................................................................................556
Spis treści 11
Maszyny stanów i obsługa reakcji ..................................................................................559Maszyny probabilistyczne...............................................................................................561
Przydatne funkcje generujące liczby losowe ............................................................563Podejmowanie decyzji.....................................................................................................564Wzorce ............................................................................................................................566
Unikanie....................................................................................................................567Atakowanie ...............................................................................................................569Uciekanie ..................................................................................................................572Celowanie .................................................................................................................573Strzelanie...................................................................................................................574
Tworzenie obiektów........................................................................................................575Łączenie elementów........................................................................................................576
Mózgi!.......................................................................................................................576Zdrowie i umieranie..................................................................................................577Dodawanie HUD-a....................................................................................................581
Uczenie się ......................................................................................................................585Wskrzeszanie botów .................................................................................................586Uczenie się botów.....................................................................................................588Rozszerzenia programu demonstracyjnego ..............................................................593
Inne podejścia do sztucznej inteligencji..........................................................................593Zespołowa sztuczna inteligencja...............................................................................594
Podsumowanie ................................................................................................................594
Rozdział 14. Skrypty gry.................................................................................... 595Książka kucharska skryptów: czego potrzebujemy ........................................................596Implementacja powiadomień wejścia i wyjścia ..............................................................597
Wyzwalacze ..............................................................................................................599Nasłuch obiektów gry......................................................................................................600Skrypty ............................................................................................................................604
Projektowanie skryptu ..............................................................................................606Wbudowywanie BeanShell .......................................................................................608
Zdarzenia opóźnione .......................................................................................................612Tworzenie zdarzeń opóźnionych w BeanShell .........................................................615
Łączymy wszystko razem ...............................................................................................616Rozszerzenia....................................................................................................................617Podsumowanie ................................................................................................................619
Rozdział 15. Trwałość — zapisywanie gry .......................................................... 621Podstawy zapisywania gier .............................................................................................621Wykorzystanie API serializacji do zapisywania stanu gry .............................................623
Wprowadzenie do serializacji ...................................................................................623Serializacja: podstawy ..............................................................................................623Serializacja: zasady...................................................................................................626Serializacja: pułapki..................................................................................................629Zmiana domyślnego działania mechanizmu serializacji...........................................633
Tworzenie zrzutu ekranu gry...........................................................................................636Tworzenie miniatury ze zrzutem ekranu...................................................................638Zapisywanie rysunku ................................................................................................639
Zapisywanie gier we właściwym miejscu.......................................................................641Podsumowanie ................................................................................................................642
12 Java. Tworzenie gier
Część III Optymalizacja i kończenie gry.......................................643
Rozdział 16. Techniki optymalizacji.................................................................... 645Zasady optymalizacji.......................................................................................................646Profilowanie ....................................................................................................................646
Testowanie wydajności .............................................................................................647Użycie programu profilującego HotSpot ..................................................................647
HotSpot............................................................................................................................651Optymalizacje specyficzne dla języka Java..............................................................652Eliminacja nieużywanego kodu ................................................................................652Wyciąganie niezmienników pętli..............................................................................653Eliminacja wspólnych podwyrażeń ..........................................................................653Propagacja stałych ....................................................................................................653Rozwijanie pętli (tylko maszyna wirtualna server) ..................................................654Metody inline ............................................................................................................654
Sztuczki optymalizacji ....................................................................................................655Algorytmy .................................................................................................................655Zmniejszanie siły operacji: przesuwanie bitów ........................................................656Zmniejszanie siły operacji: reszta z dzielenia...........................................................657Zmniejszanie siły operacji: mnożenie.......................................................................657Zmniejszanie siły operacji: potęgowanie..................................................................658Więcej na temat wyciągania niezmienników pętli....................................................658Tablice wartości funkcji............................................................................................659Arytmetyka stałoprzecinkowa ..................................................................................662Wyjątki......................................................................................................................662Wejście-wyjście ........................................................................................................662Pliki mapowane w pamięci .......................................................................................663
Wykorzystanie pamięci i zbieranie nieużytków..............................................................664Sterta Java oraz zbieranie nieużytków......................................................................664Monitorowanie zbierania nieużytków.......................................................................665Monitorowanie użycia pamięci.................................................................................666Dostrajanie sterty ......................................................................................................670Dostrajanie procesu zbierania nieużytków ...............................................................671Redukowanie tworzenia obiektów............................................................................672Ponowne wykorzystanie obiektów ...........................................................................672Pule obiektów............................................................................................................673
Zauważalna wydajność ...................................................................................................674Rozdzielczość zegara ................................................................................................674
Podsumowanie ................................................................................................................679
Rozdział 17. Tworzenie dźwięków i grafiki gry .................................................... 681Wybór wyglądu i sposobu działania gry .........................................................................682
Szukanie inspiracji ....................................................................................................682Zachowywanie spójności ..........................................................................................683
Zdobywanie darmowych materiałów do gry...................................................................683Praca z grafikami i autorami dźwięków..........................................................................684Narzędzia.........................................................................................................................685Tworzenie dźwięków ......................................................................................................685
Formaty plików dźwiękowych..................................................................................687Tworzenie tekstur i duszków...........................................................................................687
Formaty plików graficznych .....................................................................................688Tworzenie tekstur bezszwowych ..............................................................................689Tworzenie tekstur zastępczych .................................................................................690
Spis treści 13
Tworzenie tekstur przejściowych .............................................................................691Tworzenie wielopoziomowych tekstur .....................................................................692
Tworzenie obrazów tytułowych i grafiki dla wyświetlaczy HUD..................................694Tworzenie grafiki interfejsu użytkownika ......................................................................694
Dostosowywanie komponentów Swing....................................................................694Tworzenie własnych czcionek ........................................................................................696Podsumowanie ................................................................................................................701
Rozdział 18. Projekt gry i ostatnie 10% prac ...................................................... 703Ostatnie 10% prac ...........................................................................................................704
Efekty........................................................................................................................704Maszyna stanów gry .................................................................................................705
Elementy projektu gry.....................................................................................................711Środowiska................................................................................................................712Fabuła........................................................................................................................712Właściwa gra.............................................................................................................714Uczenie gracza sposobu gry......................................................................................716
Tworzenie edytora map...................................................................................................717Szukanie błędów .............................................................................................................719
Problemy z szukaniem błędów w Java2D ................................................................722Rejestrowanie zdarzeń ..............................................................................................723
Ochrona kodu ..................................................................................................................725Dystrybucja gry ...............................................................................................................726Dystrybucja gry za pomocą Java Web Start....................................................................728
Pobieranie zasobów z plików .jar .............................................................................728Podpisywanie plików .jar..........................................................................................728Tworzenie pliku JNLP ..............................................................................................729Konfigurowanie serwera WWW...............................................................................731
Dystrybucja gry w postaci kompilacji natywnej .............................................................732Aktualizacje i łatki ..........................................................................................................733Problem obciążenia serwera............................................................................................733Opinie użytkowników i testy beta...................................................................................734Zarabianie pieniędzy .......................................................................................................736Łączymy wszystko razem ...............................................................................................737Podsumowanie ................................................................................................................737
Rozdział 19. Przyszłość ..................................................................................... 739Ewolucja Javy .................................................................................................................739
Java Community Process ..........................................................................................740Bug Parade ................................................................................................................740
Przyszłość: Java 1.5 „Tiger” ...........................................................................................740Szablony (JSR 14).....................................................................................................741Wyliczenia (JSR 201) ...............................................................................................742Statyczne importowanie (JSR 201)...........................................................................743Poprawiona pętla for (JSR 201)................................................................................744Interfejs API kompilatora (JSR 199) ........................................................................744Format transferu sieciowego (JSR 200)....................................................................745Współdzielona maszyna wirtualna (JSR 121) ..........................................................745
Wymagania stawiane platformie Java.............................................................................746Potrzebne: więcej opcji dla obsługi myszy i klawiatury...........................................746Potrzebne: obsługa joysticka.....................................................................................747Potrzebne: przyspieszane sprzętowo, półprzezroczyste obrazy................................747Potrzebne: dokładniejszy zegar.................................................................................747
14 Java. Tworzenie gier
Potrzebne: grafika przyspieszana sprzętowo i tryb pełnoekranowyw systemie Linux....................................................................................................748
Potrzebne: trójwymiarowa grafika przyspieszana sprzętowo,włączona do środowiska Javy ................................................................................748
Potrzebne: optymalizacja rozkazów SIMD w maszynie HotSpot ............................749Pożądane: więcej opcji wygładzania czcionek .........................................................750Pozostałe możliwości................................................................................................752
Nowe urządzenia i Javy Games Profile (JSR 134) .........................................................752Podsumowanie ................................................................................................................753
Dodatki .......................................................................................755
Skorowidz...................................................................................... 757
Rozdział 11.
Wykrywanie kolizji
W tym rozdziale:
� Podstawy kolizji.
� Kolizje typu obiekt-obiekt.
� Kolizje typu obiekt-świat.
� Prosty program demonstracyjny wykrywający kolizje.
� Obsługa kolizji z przesuwaniem.
� Program demonstracyjny obsługujący kolizje z przesuwaniem.
� Rozszerzenia.
� Podsumowanie.
Pamiętasz grę Pong?
Niezależnie od tego, czy mamy do czynienia z piłeczką odbijaną rakietkami, laseremtrafiającym robota, poszukiwaczem skarbów wpadającym w pułapkę, bohaterem znaj-dującym dodatkową amunicję, dwoma walczącymi potworami czy po prostu z graczemidącym przy ścianie — niemal w każdej grze trzeba zastosować jakiś mechanizm wy-krywania kolizji.
W rozdziale 5., „Tworzenie dwuwymiarowej gry platformowej”, stworzyliśmy prostydwuwymiarowy system wykrywania kolizji, który świetnie się sprawdzał w przypad-ku nieskomplikowanej gry dwuwymiarowej. W tym rozdziale spróbujemy rozszerzyćomówione tam zagadnienia i więcej czasu poświęcić na wykrywanie kolizji pomiędzyobiektami (typu obiekt-obiekt) oraz pomiędzy obiektami a wielokątami przechowywa-nymi w drzewach BSP (typu obiekt-świat).
Zajmiemy się także niemniej ważnym zagadnieniem wyboru sposobu obsługi kolizji pojej wykryciu, np. poruszaniem się wzdłuż ścian lub umożliwieniem obiektom w grzesamodzielnej obsługi swojego zachowania w przypadku kolizji.
490 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
Podstawy kolizji
Wykrywanie kolizji, wbrew nazwie, tak naprawdę nie sprowadza się do samego wykry-wania. Z kolizjami związane są trzy interesujące nas zagadnienia:
� Decydowanie, które kolizje chcemy wykrywać. Byłoby stratą czasu testowanie,czy dwa obiekty ze sobą nie kolidują, jeśli znajdują się na dwóch różnych krańcachświata przedstawionego w grze. Należy się także zastanowić, czy w świeciez 1 000 poruszających się obiektów ma sens testowanie wystąpienia kolizjipomiędzy każdą parą obiektów — czyli w sumie 999 000 testów? Powinniśmywięc próbować maksymalnie ograniczyć liczbę obiektów, w przypadku którychstaramy się wykryć wystąpienie zdarzenia kolizji. Najprostszym sposobemna wprowadzenie takiego ograniczenia jest testowanie tylko obiektówznajdujących się stosunkowo blisko gracza.
� Wykrywanie kolizji. Wybór techniki wykrywania kolizji zależy od oczekiwanejdokładności kolizji w grze. Można oczywiście zastosować doskonały algorytmwykrywania kolizji i sprawdzać wszystkie wielokąty należące do obiektuze wszystkimi wielokątami tworzącymi inny obiekt, należy jednak brać poduwagę związany z takim działaniem koszt obliczeniowy. Podobnie, w świeciedwuwymiarowym moglibyśmy testować ewentualne kolizje wszystkich pikselijednego dwuwymiarowego obiektu ze wszystkimi pikselami innego obiektu.W grach komputerowych stosuje się zwykle mniej dokładne techniki wykrywaniakolizji, które jednak wykonują swoje zadanie znacznie szybciej.
� Obsługa kolizji. Jeśli dany obiekt koliduje z innym elementem sceny, należybyć przygotowanym na różne sposoby obsługi różnych typów kolizji. Przykładowo,pocisk kolidujący z robotem może spowodować zniszczenie zarówno pocisku,jak i robota. Obiekt dochodzący do ściany może się dalej przemieszczać wzdłużtej ściany. Podobnych przykładów jest wiele.
Podsumujmy — w grze powinny być podejmowane próby realizowania następującychcelów w zakresie wykrywania kolizji:
� eliminowanie jak najwięcej testów wystąpienia kolizji;
� szybkie podejmowanie decyzji, czy kolizja wystąpiła;
� zapewnianie mechanizmu wykrywania kolizji o wystarczającej precyzji;
� obsługiwanie kolizji w naturalny sposób, który nie będzie niepotrzebnie zwracałuwagi gracza podczas gry.
Ostatni cel oznacza także to, że nie powinniśmy zbytnio ograniczać możliwości ruchugracza podczas gry. Przykładowo gracz nie powinien być całkowicie zatrzymywany pokolizji ze ścianą. Zamiast tego powinniśmy umożliwić mu poruszanie się wzdłuż ścianylub spowodować jego nieznaczne odbicie.
Nie chcemy także, by nasz mechanizm wykrywania kolizji był na tyle niedokładny, bygracz mógł oszukiwać, np. chowając się w ścianie w niektórych miejscach mapy.
Rozdział 11. ♦ Wykrywanie kolizji 491
Zaczniemy od prostego algorytmu wykrywania kolizji. Wszystkie poruszające się ele-menty w grze będziemy traktować jak obiekty, niezależnie od tego, czy będzie to po-twór, gracz, pocisk lub cokolwiek innego. W przypadku każdego tak ogólnie zdefinio-wanego obiektu będziemy wykonywali następujące kroki:
1. Zaktualizuj położenie obiektu.
2. Sprawdź, czy nie występuje kolizja z innymi obiektami lub z elementamiśrodowiska.
3. Jeśli wykryto kolizję, ustaw obiekt na jego wcześniejszej pozycji.
Zauważ, że po każdym ruchu obiektu sprawdzamy, czy nie wystąpiła kolizja. Alterna-tywnym rozwiązaniem jest przeniesienie w nowe miejsca wszystkich obiektów i dopieropotem sprawdzenie występowania ewentualnych kolizji. W takim przypadku należałobyjednak przechowywać dane o poprzednich położeniach wszystkich obiektów — poja-wiłby się problem, gdyby się okazało, że trzy lub więcej obiektów powoduje kolizje.
Zauważ także, że ten podstawowy algorytm w przypadku wystąpienia kolizji po prostuodstawia obiekt na jego wcześniejsze położenie. Zwykle będziemy chcieli stosowaćinne sposoby obsługi kolizji, zależne od ich typu.
Skoro podstawowy algorytm został już omówiony, przejdźmy do wykrywania i obsługikolizji typu obiekt-obiekt w praktyce.
Kolizje typu obiekt-obiekt
Niezależnie od tego, jakiej precyzji oczekujemy od stosowanego algorytmu wykry-wania kolizji, idealnym rozwiązaniem jest wyeliminowanie maksymalnej liczby testówkolizji typu obiekt-obiekt i wcześniejsze wykonanie kilku innych testów, wskazującychna duże prawdopodobieństwo wystąpienia kolizji pomiędzy parą obiektów.
Eliminowanie testów
Jest oczywiste, że w przypadku obiektu, który nie wykonuje żadnego ruchu od ostatniejklatki, nie są potrzebne żadne testy wykrywające kolizję powodowaną przez ten obiekt.Przykqładowo skrzynia znajdująca się w pomieszczeniu nie może powodować kolizjiz żadnym innym elementem sceny. Inne obiekty mogą oczywiście kolidować z tą skrzy-nią, jednak takie kolizje są obsługiwane przez te obiekty, a nie przez statyczną skrzynię.
Aby wyeliminować maksymalną liczbę przyszłych testów na występowanie kolizji, po-winniśmy ograniczyć zbiór badanych obiektów do tych, które znajdują się w swoim bez-pośrednim sąsiedztwie.
Jednym ze sposobów takiej eliminacji jest przyporządkowanie obiektów do pól specjal-nej siatki (patrz rysunek 11.1). Każdy obiekt musi należeć do dokładnie jednego z ta-kich pól. Nawet jeśli obiekt częściowo zajmuje obszar wielu pól, trzeba zdecydować
492 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
Rysunek 11.1.Aby ograniczyć liczbę
testów na występowanie
kolizji typu obiekt-obiekt,
możemy przyporządkować
obiekty do pól siatki
i wykonywać testy dla
obiektów znajdujących
się w tych samych
i sąsiadujących polach
o jego przyporządkowaniu do dokładnie jednego z nich. Dzięki temu obiekt będzie mu-siał testować wystąpienie kolizji wyłącznie z obiektami z pola, w którym się znajduje,oraz z pól sąsiadujących z tym polem.
Innymi sposobami izolowania obiektów jest tworzenie siatek jedno- i trójwymiarowych.Przykładowo, w dwuwymiarowej grze przewijanej, obiekty można posortować zgod-nie z ich współrzędną x, dzięki czemu będzie można wykonywać testy tylko dla obiek-tów sąsiadujących na liście. W przypadku gier trójwymiarowych obiekty można od-izolować za pomocą siatki trójwymiarowej zamiast dwuwymiarowej — każda komórkabędzie wówczas miała kształt sześcianu, nie kwadratu. W tym rozdziale do wykrywa-nia kolizji w grach z mechanizmem trójwymiarowym będziemy jednak stosowali siatkęw prostszej wersji dwuwymiarowej.
Izolowanie obiektów za pomocą siatki umożliwia także łatwe usuwanie obiektów zesceny. Przykładowo możemy zastosować rozwiązanie, w którym rysowane są tylkoobiekty w widocznych polach. Jeśli wykorzystujemy drzewo BSP, możemy rysować tyl-ko te obiekty, które znajdują się w polach z widocznymi liśćmi.
Kod przypisujący obiekty do pól siatki jest trywialny — na potrzeby przykładów z tegorozdziału zaimplementowaliśmy go w klasie ������������ ������. Kiedy obiekt jestaktualizowany, wywoływana jest metoda �������������������� (patrz listing 11.1),która odpowiada za wykrywanie ewentualnych kolizji pomiędzy tym obiektem a obiek-tami znajdującymi się w tych samych i w przylegających polach siatki.
Listing 11.1. Sprawdzanie przylegających komórek (plik GridGameObjectManager.java)
������������������� ������������������������������������������������������������ ������������� ��������� ��������������������!����"����������#��������� � �����#
�������$%�!���������������&� ��'�("���$%#�������� ������&�)���#����**
Rozdział 11. ♦ Wykrywanie kolizji 493
���
�������+������,���(��� (��������������������(�����������������-(���������������������������� �����.������������ $/��.����������,�0���12����"������ %!
��������� ��������� �&�)���#
�������34(������-��� (���$5,�%������������$���(�������������%������ ��5�&��� �6��7��/��7$$� �%��������7$%%#����� ��(�&��� �6��8��/��8$$� �%��������9$%%#
�������+������:��������������;�(�������������)��$� ���&5<=#��>&5?=#��??%�!��������)��$� ���&(<=#��>&(?=#��??%�!��������������������&������$�,��%#�������������)�$����@&� ���%�!������������������������ �A&��������� 2����� �����.����$�����,�����������,�������������������"������ %#������������*��������*����*
������ ��������� #*
Powyższy kod wywołuje zdefiniowaną w klasie ������������������ metodę ������������, która wykrywa kolizję pomiędzy danym obiektem a listą obiektów. Imple-mentacją klasy ������������������ zajmiemy się za chwilę.
Sfery otaczające
Niedokładną, ale szybką techniką wykrywania kolizji jest zastosowanie tzw. sfer otacza-jących; przykład takiej sfery otaczającej obiekt przedstawia rysunek 11.2.
Rysunek 11.2.Do wykrywania kolizji
można użyć sfer otaczających
Kiedy sfery otaczające dwa obiekty kolidują ze sobą, ich kolizja jest traktowana jakkolizja otaczanych przez nie obiektów. Oto nasza pierwsza próba zaimplementowaniatestu wykrywającego kolizję dwóch sfer otaczających:
494 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
�5�&������'�5�<������B�5#�(�&������'�(�<������B�(#���&������'���<������B��#�� 2���� ��&������'�������?������B������#�)�$6�����C�$�5��5�?��(��(�?������%�>��� 2���� �%�!�������D(�(�����������*
Wywołanie funkcji ���������� wiąże się jednak z wykonaniem dużej ilości obliczeń.Możemy uniknąć tego wywołania, podnosząc do kwadratu obie strony nierównościi otrzymując prostsze oraz znacznie szybciej obliczane wyrażenie warunkowe:
�)�$�5��5�?��(��(�?�������>��� 2���� ����� 2���� �%�!�������D(�(�����������*
Jeśli Twoja gra wyświetla obraz dwuwymiarowy zamiast scen trójwymiarowych, za-miast kolizji sfer możesz testować wystąpienia kolizji okręgów, wystarczy usunąć z rów-nań składniki odnoszące się do współrzędnej z.
Testowanie występowania kolizji pomiędzy sferami otaczającymi jest stosunkowo pro-ste, ale także bardzo niedokładne. Przykładowo na rysunku 11.3 widać sferę otaczającągracza, która koliduje ze sferą otaczającą robota, chociaż same obiekty gracza i robotawcale ze sobą nie kolidują.
Rysunek 11.3.Niedokładność sfer
otaczających: para
sfer ze sobą koliduje,
mimo że otaczane
obiekty znajdują się
w pewnej odległości
Oczywiście taka niedokładność w wielu grach nie będzie dla gracza zauważalna. Przy-kładowo w przypadku szybkiej gry akcji, w której biegamy po pomieszczeniach orazpodnosimy apteczki i amunicję, prawdopodobnie nie będzie dla nas miało znaczenia, czypodnosimy te obiekty na moment przed ich faktycznym dotknięciem. Jednak w innychsytuacjach taki brak precyzji może być irytujący, np. kiedy uda Ci się zranić przeciw-nika, którego nawet nie dotknąłeś.
Po otrzymaniu pozytywnego wyniku testu kolizji sfer otaczających możemy pójść krokdalej i wykonać bardziej szczegółowe testy, np. sprawdzić ewentualne występowaniekolizji pomiędzy wszystkimi parami wielokątów tworzących oba obiekty.
Inną metodą jest wykorzystanie do testów zbioru sfer otaczających (patrz rysunek 11.4).Na rysunku dla robota skonstruowano trzy sfery otaczające, które bardziej precyzyjnieopisują jego kształt. Po otrzymaniu pozytywnego wyniku testu kolizji podstawowych(najmniej dokładnych) sfer otaczających możemy przetestować drugi (bardziej dokład-ny) zbiór sfer. Jeśli którakolwiek ze zbioru sfer gracza koliduje z którąkolwiek ze zbiorusfer robota, wówczas możemy uznać, że oba obiekty ze sobą kolidują.
Rozdział 11. ♦ Wykrywanie kolizji 495
Rysunek 11.4.
Wiele sfer otaczających można
wykorzystać do przeprowadzania
bardziej precyzyjnych testów
występowania kolizji
Mamy więc dwa poziomy sfer dla wszystkich obiektów w grze. Nie musimy oczywiściena tym poprzestawać. Moglibyśmy dodać jeszcze kilka poziomów, z których każdyopierałby się na większej liczbie sfer otaczających i zapewniałby większą dokładność.Taka technika jest często nazywana drzewem sfer lub podziałem sfer. Możemy w tensposób szybko wykluczyć z przetwarzania obiekty, które ze sobą nie kolidują, oraz wy-konać bardziej precyzyjne testy dla obiektów powodujących potencjalną kolizję. Oma-wiane podejście pozwala nam także stwierdzić, która część obiektu została trafiona,dzięki czemu możemy wykrytą kolizję odpowiednio obsłużyć. Przykładowo robota tra-fionego pociskiem rakietowym możemy pozbawić uszkodzonej nogi.
Zauważ, że drzewa sfer otaczających musza się obracać wraz z obracającym się otacza-nym obiektem. Przykładowo sfery muszą zmieniać swoje położenie wraz ze zmianąpołożenia ramienia robota. W kodzie zaprezentowanym w rozdziale 9., „Obiekty trój-wymiarowe”, zdefiniowaliśmy trójwymiarowe obiekty reprezentowane jako zagnież-dżone grupy wielokątów. Ponieważ była to już struktura drzewiasta, w celu zaimple-mentowania drzewa sfer możemy nadać każdej grupie wielokątów jej własny zbiór sferi zapewnić przełożenie ruchu grup na odpowiedni ruch sfer. W tym rozdziale nie bę-dziemy implementować drzew sfer, warto jednak brać pod uwagę takie rozwiązanie pod-czas tworzenia gier.
Podsumujmy: przed narysowaniem typowej klatki większość obiektów nie wymagaprzeprowadzania testów wystąpienia kolizji. W niektórych przypadkach konieczne jestprzeprowadzenie prostego testu, a kilka obiektów wymaga najbardziej skomplikowa-nych i kosztownych obliczeniowo testów na wystąpienie kolizji.
Walce otaczające
Alternatywą dla sfer otaczających są pionowe walce otaczające (patrz rysunek 11.5). Ta-kie rozwiązanie pozwala zredukować testy na występowanie kolizji do sprawdzenia dwu-wymiarowych okręgów i testów położenia pionowych linii (a więc w jednym wymiarze).
496 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
Rysunek 11.5.Do wykrywania kolizji
można także wykorzystać
pionowy walec otaczający
Pionowe walce otaczające najlepiej nadają się do — lepszego niż w przypadku poje-dynczej sfery otaczającej — opisywania wysokich, cienkich obiektów (np. graczy lubpotworów). W tym rozdziale w naszym mechanizmie trójwymiarowym zaimplemen-tujemy wykrywanie kolizji typu obiekt-obiekt właśnie przy wykorzystaniu pionowychwalców otaczających.
Całość prezentowanego kodu odpowiadającego za proste wykrywanie kolizji umie-ściliśmy w klasie ������������������. Zawarte w tej klasie metody obsługujące kolizjetypu obiekt-obiekt przedstawiono na listingu 11.2.
Listing 11.2. Sprawdzanie obiektów CollisionDetection.java
�������+������,���(��� (���������������������� (��� (������������������(�� (�� �������� ���������������������� �����.����$/��.����������',�"����������,�0���12����"������ %!��������� ��������� �&�)���#����)��$� ���&E#��>����������$%#��??%�!��������/��.����������B�&�$/��.����%���������$�%#���������������� �A&�����.����$�����',������B,���������������"������ %#����*������ ��������� #*
�������9����������F���,���������������� ������(������;��������;�����.�����'�����������,���������B�������������� ����6������(���(������������(�(�� �������������� ���������������;��$����;�-����������%��������������� �����.����$/��.����������',����/��.����������B,�0���12����"������ %!�������.����� ����4���������F������(�����;������)�$�����'�&&������B%�!���������� �)���#����*
Rozdział 11. ♦ Wykrywanie kolizji 497
����G��(�� /���B�� ������ ��'�&������'���B�� ��$%#����G��(�� /���B�� ������ ��B�&������B���B�� ��$%#
�������H��������������(��������������(�$���-����(,�4��(�����F��������-�%�����)�����'(=�&������'���8$%�?���� ��'���B�����I����$%#����)�����'(J�&������'���8$%�?���� ��'���K��I����$%#����)�����B(=�&������B���8$%�?���� ��B���B�����I����$%#����)�����B(J�&������B���8$%�?���� ��B���K��I����$%#�����)�$B(J�>�'(=�AA�B(=�L�'(J%�!���������� �)���#����*
�������H����� ����������(������(���(�<��������������� ��5���������$��;�-(�����������������%�����)������5�&������'���7$%�<������B���7$%#����)��������&������'���9$%�<������B���9$%#����)������� 2����&���� ��'���M�����$%�?���� ��B���M�����$%#����)���������+C�&��5��5�?������#����)������� 2���+C�&��� 2�������� 2���#�����)�$����+C�>��� 2���+C%�!����������� ��� ��.������������ $�����',������B,�����+C,�������������� 2���+C,����"������ %#����*������ �)���#*
�������.��-���������������������.�����'�����������,� ���������������B������(�����������,������(����������������'��������������� ��� ��.������������ $/��.����������',�/��.����������B,)���������+C,�)������� 2���+C,�0���12����"������ %!���������'� ���)(.������������ $�����B%#������ ���#*
W powyższym kodzie obiekty w grze są związane z obiektami klasy ������������� �����, które otaczają tworzące je grupy wielokątów odpowiednimi walcami. Opis wal-ca otaczającego składa się z promienia podstawy walca oraz wysokości, na jakiej znaj-duje się podstawa dolna walca (zwykle 0) i podstawa górna.
Metoda ����������� jedynie sprawdza, czy dwa walce otaczające ze sobą kolidują;jeśli tak się dzieje, wywoływana jest metoda ���������������������.
Metoda ��������������������� jedynie sygnalizuje (za pomocą metody ����!�����������������) poruszającemu się obiektowi, że jego ruch spowodował kolizję. Ta i innemetody umożliwiające sygnalizowanie podobnych zdarzeń znajdują się w klasie ���������, nie ma w ich przypadku jednak domyślnie zdefiniowanych działań — w raziepotrzeby podklasy klasy �������� mogą przesłaniać te metody. Przykładowo zdefinio-wana w klasie ���� metoda ����!���������������� jest wykorzystywana do niszcze-nia robota, który koliduje z pociskiem reprezentowanym przez obiekt tej klasy:
498 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
������� ���� ���)(.������������ $/��.����������%�!�������H�����(�������������������������)�$������� ��� ��)�B��%�!����������+���$�����,�+K'KNO2N+KM.8N2%#����������+���$+K'KNO2N+KM.8N2%#����**
Na razie w klasie ������������ ������ zastosujemy rozwiązanie, w którym poru-szający się obiekt powodujący kolizję jest przenoszony do swojej poprzedniej lokaliza-cji. W przyszłości opracujemy bardziej realistyczną reakcję na kolizje typu obiekt-obiekt,czyli przemieszczanie się wzdłuż obiektu.
Problem przetwarzania dyskretno-czasowego
Typowa gra aktualizuje swój stan w dyskretnych odstępach czasowych — w taki wła-śnie sposób aktualizujemy położenie każdego obiektu na podstawie czasu, jaki upłynąłod ostatniej aktualizacji. Przykładowo na rysunku 11.6 widać widziany z góry ruchobiektu, ujęty w kolejnych odstępach czasu. Widać wyraźnie, jak poruszający się obiektkoliduje z większym obiektem w trzeciej klatce.
Rysunek 11.6.
Widziane z góry kolejne
lokalizacje poruszającego
się obiektu
Niestety, taki sposób obsługi ruchu obiektów może uniemożliwiać prawidłowe wykry-wanie kolizji. Wyobraź sobie, że obiekt porusza się szybciej lub szybkość odtwarza-nia klatek jest mniejsza. W takiej sytuacji poruszający się obiekt może „minąć” obiekt,z którym faktycznie powinien kolidować. Przykładowo na rysunku 11.7 poruszającysię obiekt koliduje z większym obiektem pomiędzy drugą a trzecią klatką.
Rysunek 11.7.
Problem powodowany
przez przetwarzanie
dyskretno-czasowe:
obiekt może „minąć”
inny obiekt w sytuacji,
gdy powinna zostać
wykryta kolizja
Rozdział 11. ♦ Wykrywanie kolizji 499
Istnieje kilka rozwiązań tego problemu. Bardziej precyzyjnym, ale też bardziej kosztow-nym obliczeniowo sposobem jest połączenie walców (lub innych brył) otaczającychporuszający się obiekt w jedną bryłę, od początkowej do końcowej lokalizacji (patrzrysunek 11.8).
Rysunek 11.8.Poruszający się obiekt
można traktować jak
„rurę”, co rozwiązuje
problem powodowany
przez przetwarzanie
dyskretno-czasowe
Alternatywnym rozwiązaniem jest testowanie wystąpień kolizji w dodatkowych punk-tach pomiędzy początkową i końcową lokalizacją poruszającego się obiektu. Na rysun-ku 11.7 takie punkty moglibyśmy dodać w połowie odległości pomiędzy każdą klatką.
Kolizje typu obiekt-świat
Kolizje obiektów ze środowiskiem, w którym występują, powinny być obsługiwane zeszczególną starannością. Nie chcemy przecież, by gracz lub inny obiekt mógł przechodzićprzez ścianę lub by nienaturalnie się trząsł podczas przemieszczania się wzdłuż ściany.
W rozdziale 5. zaimplementowaliśmy kolizje typu obiekt-świat, zmieniając w tym sa-mym czasie tylko jedną współrzędną (najpierw x, potem y), co sprawdzało się doskonalew przypadku prostego świata dwuwymiarowego, w którym obiekty nie przemieszczająsię szybciej niż o jedną jednostkę w klatce.
W trójwymiarowym świecie nie istnieją tak zdefiniowane jednostki — zwykle możemyjednak opisać taki świat za pomocą struktury ułatwiającej wykrywanie kolizji, np. drze-wa BSP. Do zaimplementowania kolizji obiektów z podłogami, sufitami i ścianami wy-korzystamy opracowane w poprzednim rozdziale dwuwymiarowe drzewo BSP.
Prostopadłościany otaczające,wykorzystywane do wykrywania kolizji z podłogami
W dwuwymiarowej grze, stworzonej w rozdziale 5., do wykrywania kolizji potrzebo-waliśmy prostokątów otaczających. W środowisku trójwymiarowym, poza stosowa-niem sfer, okręgów, walców i prostopadłościanów otaczających, istnieje jeszcze kilkainnych popularnych mechanizmów wykrywania kolizji. Dostępne są dwa typy prosto-padłościanów otaczających: o dowolnym ustawieniu i dopasowane do osi. Prostopa-dłościany otaczające o dowolnym ustawieniu można swobodnie obracać, natomiastprostopadłościany dopasowane do osi muszą zawsze być wyrównane do osi x, y i z.W tym rozdziale będziemy wykorzystywali pionowe walce otaczające do wykrywania
500 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
kolizji typu obiekt-obiekt, natomiast do wykrywania kolizji typu obiekt-świat użyje-my dopasowanych do osi prostopadłościanów otaczających. W pierwszej kolejnościzajmiemy się kolizjami z podłogami i sufitami. Chcielibyśmy, by w środowisku, w któ-rym podłogi mogą się znajdować na różnych wysokościach, obiekty znajdowały się nanajwyższym poziomie podłogi pod prostopadłościanem otaczającym (patrz rysunek 11.9).Podobnie nie chcemy, by obiekty poruszały się w obszarach, gdzie strop jest dla nichzbyt niski. Chcielibyśmy także umożliwić obiektom w grze pokonywanie niewysokichstopni bez zatrzymywania. W sytuacji przedstawionej na poniższym rysunku gracz mo-że płynnie pokonać stopień znajdujący się nieznacznie wyżej niż podłoga.
Rysunek 11.9.Kolizja prostopadłościanu
otaczającego z podłogą
(stopniem): prostopadłościan
otaczający gracza częściowo
znajduje się na stopniu,
zatem wysokość tego stopnia
jest wykorzystywana
jako wysokość „podłogi”
pod graczem
Na rysunku 11.9 najwyższy poziom pod zastosowaną bryłą otaczającą obiekt jest wyko-rzystywany do wyznaczenia wysokości, na której ten obiekt się znajduje. Testując wy-stępowanie ewentualnych kolizji pomiędzy obiektem a podłogą lub sufitem w danympomieszczeniu, możemy sprawdzić, czy którykolwiek z wierzchołków prostopadłościa-nu nie znajduje się pod powierzchnią podłogi lub nad powierzchnią sufitu. Oznaczato, że sprawdzenie, na jakiej wysokości powinien się znaleźć obiekt, wymaga przete-stowania czterech wierzchołków prostopadłościanu otaczającego.
Warto zaznaczyć, że prostopadłościany otaczające można wykorzystać także do wy-krywania kolizji typu obiekt-obiekt. Możemy także stworzyć drzewo prostopadłościa-nów otaczających, tak jak drzewo sfer otaczających.
Znajdowanie liścia drzewa BSP dla danego położenia
Informacje o podłodze są przechowywane w liściu dwuwymiarowego drzewa BSP.Istnieje możliwość stosunkowo łatwego odszukania właściwego liścia dla danej loka-lizacji — wystarczy wykorzystać algorytm podobny do tego, za pomocą którego prze-glądaliśmy drzewo w poprzednim rozdziale (patrz listing 11.3).
Listing 11.3. Metoda getLeaf() dostępna w pliku BSPTree.java
�������9��������F,������(��� ������������ ���������-��� (���5,������������"�)���"�)$)�����5,�)������%�!������ ���"�)$���,�5,��%#*
Rozdział 11. ♦ Wykrywanie kolizji 501
�������"�)���"�)$H��� ��,�)�����5,�)������%�!�����)�$ ���&&� ����AA� ���� ��� ��)�"�)%�!���������� �$"�)% ��#����*����� ������&� ���������� ���+��K�� $5,��%#�����)�$����&&�B+G"� �B'��%�!���������� ���"�)$ �������,�5,��%#����*�������!���������� ���"�)$ ���)� �,�5,��%#����**
Za pomocą powyższej metody znajdujemy oczywiście liść tylko dla jednej lokalizacji,natomiast prostopadłościan otaczający obiekt może teoretycznie rozciągać się na kilkaliści. Oznacza to, że powinniśmy znajdować liście dla wszystkich wierzchołków pro-stopadłościanu otaczającego.
Implementacja testów wysokości podłogi i sufitu
Testowanie wszystkich wierzchołków prostopadłościanu otaczającego w porównaniuz wysokościami podłogi i sufitu jest realizowane za pomocą kilku metod dostępnychw klasie ������������������ (patrz listing 11.4).
Listing 11.4. Sprawdzanie kolizji z podłogą i sufitem (plik CollisionDetection.java)
�������D�����-����������;��������������;��(���(��(�� ��������(�(�� �������������������(��������;�����$���-�������������)�����%,�������(�� (����������B+G��D�����-����;��������;����� ������� �������������� ������� �������������������������,���������� ��������� (����� �������� ����������)� ���G�� �J2�P����QR��.MHNM+�&�!���� ��G�� �J2�P����$<=,�<=%,� ��G�� �J2�P����$<=,�=%,���� ��G�� �J2�P����$=,�=%,� ��G�� �J2�P����$=,�<=%,*#
���
������P���' ����� �$�����%#��������P���' ����� �$�����,������K��%#
���
�������9�������������������;�����-��������)��������� ������������������$�����������(�/��.����%��D(��-�������(������������P���I����$%��������������I����$%���������������� ���������� �������������������-��������)������������� ������P���' ����� �$/��.����������%�!����)�����5�&���������7$%#����)�������&���������9$%#
502 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
����)������&���������B�� ��$%���M�����$%�<�=#����)�����)���I�����&�P�����6SHO0'"3N#����)��������I�����&�P�����6'7O0'"3N#����B+GK�"�)���)�&����K���"�)$5,��%#�����)�$��)�@&� ���%�!��������)���I�����&���)�)���I����#�����������I�����&���)����I����#����*
�������+����������(��������;���� ��(�����)��$� ���&E#��>�.MHNM+�� ���#��??%�!��������)�����5.))���&�����.MHNM+Q�R�5#��������)������.))���&�����.MHNM+Q�R�(#����������)�&����K���"�)$5�?�5.))��,���?��.))��%#���������)�$��)�@&� ���%�!������������)���I�����&�6������5$)���I����,���)�)���I����%#���������������I�����&�6������ $���I����,���)����I����%#��������*����*
������������P���I����$)���I����%#���������������I����$���I����%#*
�������+������,���(��������������������-��;�����)��������D(���(���������(���������P���I����$%��������������I����$%����������(�� �����������������;�(������-��������)������������ ��������P���' ����� �$/��.����������,��� �������K��%!��������� ��������� �&�)���#
����)�����)���I�����&���������P���I����$%#����)��������I�����&������������I����$%#����)�����������I�����&���������B�� ��$%���B�����I����$%#����)��������I�����&���������B�� ��$%���K��I����$%#
�����)�$@��������P�(� �$%%�!�����������������"������ $%�(�&�)���I�����<�������I����#����*�������+������,���(�����F�������� ��� ������������ �4�����-���������)�$��������8$%�?�������I�����>�)���I����%�!�������������� ���)(P����������� $%#����������������K� �)��$%���0�����($%�(�&�E#����������������"������ $%�(�&�)���I�����<�������I����#����*�������+������,���(�����F�������� ��� �������������(4����)������������)�$��������8$%�?����I�����L����I����%�!�������������� ���)(���� ��������� $%#����������������K� �)��$%���0�����($%�(�&�E#����������������"������ $%�(�&����I�����<����I����#����*
*
Rozdział 11. ♦ Wykrywanie kolizji 503
Metoda ���"����#����������� zwraca wysokość, na jakiej znajduje się podłoga i sufitw miejscu, gdzie znajduje się obiekt — weryfikuje dane z liści odpowiadających po-łożeniu czterech wierzchołków obiektu. Pamiętaj, że w danym momencie obiekt możesię znajdować w więcej niż jednym liściu drzewa BSP.
Do ustawiania położenia obiektu w osi y wykorzystujemy metodę �����"����#������������. Jeśli obiekt nie unosi się w powietrzu, wartość y odpowiada wysokości, najakiej znajduje się podłoga. W przeciwnym przypadku metoda sprawdza, czy obiekt niekoliduje z podłogą lub sufitem. Jeśli tak się dzieje, wywoływana jest udostępniana przezobiekt metoda ����!�"��������������� lub ����!�������������������. Podobnie jakw przypadku metody ����!����������������, wymienione dwie metody nie majądomyślnie zdefiniowanych działań — podklasy klasy �������� mogą przykrywaćte metody.
Zaprezentowany sposób implementowania kolizji z podłogą i sufitem jest dosyć pry-mitywny — ruch gracza jest mało realistyczny. W dalszej części tego rozdziału zaim-plementujemy efekt grawitacji i możliwość płynnego poruszania się po schodach, dziękiczemu mechanizm obsługi kolizji stanie się znacznie bardziej realistyczny.
Prostopadłościany otaczające,wykorzystywane do testowania kolizji ze ścianami
W przypadku podłóg i sufitów przeprowadzaliśmy testy na wystąpienia kolizji dopie-ro po tym, jak interesujący nas obiekt wykonał jakiś ruch — mogliśmy dzięki temuokreślić, na jakiej wysokości znajduje się podłoga pod obiektem.
Ściany są jednak cienkimi liniami, zatem jeśli będziemy przeprowadzać testy na wystą-pienie kolizji tylko po wykonaniu przez obiekt ruchu, istnieje możliwość, że nasza re-akcja będzie spóźniona i nie zarejestrujemy przejścia obiektu przez ścianę. Aby dokład-nie wykrywać, czy obiekt uderzył w ścianę, trzeba analizować całą drogę przebytą przezobiekt od czasu ostatniej aktualizacji (między kolejnymi klatkami).
Jeśli używamy dwuwymiarowego drzewa BSP, droga przebyta przez obiekt pomiędzydwiema kolejnymi klatkami jest odcinkiem, możemy więc sprawdzać, czy istnieje punktprzecięcia tego odcinka z którąkolwiek z linii reprezentujących ścianę (podobne rozwią-zanie moglibyśmy zastosować w przypadku trójwymiarowego drzewa BSP — wówczasbadalibyśmy istnienie punktu przecięcia prostej reprezentującej przebytą drogę z płasz-czyzną reprezentującą ścianę).
Obiekty są oczywiście bryłami, a nie punktami. Jeśli więc do wykrywania kolizji uży-wamy prostopadłościanów otaczających obiekty, konieczne jest testowanie wszystkichczterech wierzchołków podstawy prostopadłościanu otaczającego ze ścianami na scenie(patrz rysunek 11.10). Na poniższym rysunku testujemy punkty przecięcia czterech ście-żek (po jednej dla każdego wierzchołka) ze ścianą — takie punkty istnieją dla trzechścieżek.
Jeśli wykryjemy więcej niż jeden punkt przecięcia (jak na rysunku 11.10), do obsługikolizji wykorzystujemy najkrótsza ścieżkę od punktu startowego do punktu przecięcia(patrz rysunek 11.11). W tym przypadku lewy górny wierzchołek otoczenia obiektu jest
504 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
Rysunek 11.10.Sprawdzanie punktów
przecięcia ścian i prostych
reprezentujących ścieżki
przebyte przez wierzchołki
podstawy prostopadłościanu
otaczającego obiekt. Każdy
odcinek jest porównywany
w ten sposób ze wszystkimi
ścianami przechowywanymi
w drzewie BSP
Rysunek 11.11.Miejsce kolizji jest określane
na podstawie tego wierzchołka
prostopadłościanu
otaczającego, który znajduje
się najbliżej odpowiedniego
punktu przecięcia
tym punktem, który jako pierwszy koliduje ze ścianą (znajduje się najbliżej odpowiednie-go punktu przecięcia), zatem właśnie w oparciu o ten punkt wyznaczamy miejsce kolizji.
Trzeba znaleźć możliwie szybką metodę określania, czy istnieje punkt przecięcia danejścieżki z którymkolwiek z wielokątów trójwymiarowego świata. Jeśli taki punkt istnie-je, należy znaleźć pierwszy odcinek kolizji w drzewie BSP.
Punkt przecięcia z odcinkiem wielokątareprezentowanego w drzewie BSP
Rozważmy ścieżkę z punktu (x1, y1) do punktu (x2, y2). Naszym celem jest znalezie-nie najbliższego punktu przecięcia (jeśli w ogóle taki punkt istnieje) tej ścieżki z do-wolnym wielokątem przechowywanym w drzewie BSP. Najbliższy punkt przecięciato taki, który znajduje się najbliżej punktu (x1, y1).
Rozdział 11. ♦ Wykrywanie kolizji 505
Oto algorytm realizujący to zadanie, począwszy od korzenia drzewa BSP:
1. Sprawdź istnienie punktu przecięcia ścieżki z podziałem reprezentowanymprzez ten węzeł. Jeśli ścieżka znajduje się z przodu lub z tyłu linii podziału,sprawdź odpowiednio przednie lub tylne węzły.
2. W przeciwnym przypadku — jeśli ścieżka przecina linię podziału — podzieltę ścieżkę w punkcie przecięcia z linią podziału na dwie ścieżki. Jedna ścieżkareprezentuje wówczas pierwszą część ścieżki, druga reprezentuje drugą częśćtej samej ścieżki.
a. Sprawdź, czy istnieją ewentualne punkty przecięcia pierwszej część ścieżki(patrz krok 1).
b. Jeśli nie znajdziesz punktu przecięcia, sprawdź, czy nie istnieją punktyprzecięcia z wielokątami przechowywanymi w tym węźle.
c. Jeśli nie znajdziesz punktów przecięcia, sprawdź, czy nie istnieją punktyprzecięcia drugiej części ścieżki z wielokątami przechowywanymi w tymwęźle (patrz krok 1).
d. Jeśli znajdziesz punkt przecięcia, zwróć dane tego punktu. W przeciwnymprzypadku zwróć wartość ����.
Mówiąc najprościej, zadaniem powyższego algorytmu jest zbadanie wszystkich liniipodziałów przecinających się ze ścieżką — od pierwszej (najbliższej) do ostatniej (naj-dalszej) linii podziału — i zwrócenie pierwszego znalezionego punktu przecięcia (jeślitaki punkt w ogóle istnieje).
Zauważ, że fakt wzajemnego przecinania się ścieżki z linią podziału nie musi oznaczaćwystępowania kolizji. Aby taka kolizja zaistniała, muszą być spełnione trzy warunki:
� Ścieżka musi przecinać przechowywany w drzewie BSP odcinek, który reprezentujewielokąt.
� Wielokąt nie może być na tyle mały, aby obiekt mógł przejść nad nim, oraz musiznajdować się na wysokości uniemożliwiającej swobodne poruszanie się obiektu(nie może być ani za nisko, ani za wysoko).
� Ścieżka musi prowadzić od przedniej do tylnej strony wielokąta.
Algorytm znajdujący punkt przecięcia (i sprawdzający powyższe warunki występowa-nia kolizji) zaimplementowaliśmy za pomocą kodu przedstawionego na listingu 11.5.
Listing 11.5. Punkt przecięcia z odcinkiem wielokąta reprezentowanego w drzewie BSP
(plik CollisionDetection.java)
�� ���B+GK����K#�� ���B+G"� �����#�� ���G�� �J2�P������ ������ #
���
506 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
�������9������� ������������$��������������� ��%��������(����4�;����$5=,�=%<L$5J,�J%������� ������ ���� (����������B+G�����9���������������(����� � (�������B+GG��(�� ,�����������F� ����$�������� ����� ���4�� ��� �����������%����������B+GG��(�� ���P���D���S ������ $)�����5=,�)������=,�)�����5J,�)������J,)�����(B�����,�)�����(K��%!������ ���P���D���S ������ $���K���M���$%,�5=,��=,�5J,��J,�(B�����,�(K��%#*
�������9������� ������������$��������������� ��%��������(����4�;����$5=,�=%<L$5J,�J%������� ������ ���� (����������B+G,�����;���(��������� ������-���9���������������(����� � (�������B+GG��(�� ,��������������F� ����$����� ����� ���4�� ��� �����������%����������B+GG��(�� ���P���D���S ������ $B+GK�H��� ��,�)�����5=,�)������=,)�����5J,�)������J,�)�����(B�����,�)�����(K��%!�����)�$ ���&&� ����AA� ���� ��� ��)�B+GK�"�)%�!���������� � ���#����*
����� �������&� ���������� ���+��K����$5=,��=%#����� �� ��&� ���������� ���+��K����$5J,��J%#����)������ ������ 7#����)������ ������ 9#
�����)�$ ��&&�B+G"� ��.""SHN'M%�!�������� ��&�����#����*
�����)�$�����&&�B+G"� ��.""SHN'M%�!��������� ������ 7�&�5=#��������� ������ 9�&��=#����*��������)�$�����@&� �%�!���������������"� $5=,��=,�5J,��J%#�������� ���������� ���S ������ G�� �$����,� ������ %#��������� ������ 7�&�� ������ �5#��������� ������ 9�&�� ������ �(#����*��������!��������� ������ 7�&�5J#��������� ������ 9�&��J#����*
�����)�$�����&&�B+G"� ��.""SHN'M�TT������&&� �%�!���������� � ���#����*
Rozdział 11. ♦ Wykrywanie kolizji 507
�������+���������� �;�����F��� ���������-�������)�$�����@&�B+G"� ��.""SHN'M%�!��������B+GG��(�� ������&���P���D���S ������ $������������$�����&&�B+G"� �PM.HK%U ���)� �V �������,������������5=,��=,�� ������ 7,�� ������ 9,������������(B�����,�(K��%#���������)�$�����@&� ���%�!�������������� �����#��������*����*
�������K���������� ��������������)�$�����@&� ��AA������&&�B+G"� ��.""SHN'M%�!��������B+GG��(�� ������&���D����������� $ ������(�� �,����������������5=,��=,�5J,��J,�(B�����,�(K��%#���������)�$�����@&� ���%�!������������� ������ ���"������ $� ������ 7,����������������� ������ 9%#�������������� �����#��������*����*
�������+��������(� ;�����F��� ���������-�������)�$�����@&� �%�!��������B+GG��(�� ������&���P���D���S ������ $������������$ ��&&�B+G"� �PM.HK%U ���)� �V �������,������������� ������ 7,�� ������ 9,�5J,��J,������������(B�����,�(K��%#���������)�$�����@&� ���%�!�������������� �����#��������*����*
�������H��� ����� ���� ������������������� � ���#*
�������+������,���(������ �����4����������������(��������������(���������;�����4;�(��� ���� ����W��4������� ���� ����� ���� ;�������������;�(,��� ��� ���������� �������,�4����� ��������������;�(����������B+GG��(�� ���D����������� $"�������(�� �,�)�����5=,�)������=,�)�����5J,)������J,�)�����(B�����,�)�����(K��%!�����������"� $5=,��=,�5J,��J%#����)��$� ���&E#��>���(�� �����$%#��??%�!��������B+GG��(�� ����(�&�$B+GG��(�� %���(�� ����$�%#��������B+G"� ������&����(���"� $%#
�����������+������,���(� ������������� �����������)�$�����&&� ���%�!�������������� �� �#��������*
508 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
�����������+������,���(�� ���������� �����������(��������$����-��� ��(%�������� �����������)�$���������>&�(B������AA�������������L�(K��%�!�������������� �� �#��������*
�����������+������,���(����� �����(�����������(-������ (����������)�$�������+��K�� $5J,��J%�@&�B+G"� �B'��%�!�������������� �� �#��������*
�����������+������,���(����4������� �����;����� ����������� �����=�&��������+��K�� $�����5=,������(=%#��������� �����J�&��������+��K�� $�����5J,������(J%#���������)�$���=�@&����J%�!�������������� ����(#��������*����*������ � ���#*
W powyższym kodzie metoda ���"����$���%������������� odpowiada za realizacjęomówionego wcześniej algorytmu, natomiast metoda ���$�������������� sprawdzawymienione warunki istnienia kolizji pomiędzy ścieżką ruchu obiektu a wielokątem.
Gdybyśmy wykorzystywali trójwymiarowe drzewo BSP, konieczne byłoby napisaniepodobnego kodu do określania wysokości, na jakiej znajduje się podłoga pod obiek-tem. Wystarczyłoby użyć tego samego algorytmu do znajdowania najwyżej znajdują-cego się wielokąta pod graczem, czyli znaleźć pierwszy punkt przecięcia z odcinkiemznajdującym się bezpośrednio pod obiektem.
Mamy już niemal wszystkie potrzebne składniki implementacji kolizji prostopadło-ścianu otaczającego z wielokątami przechowywanymi w drzewie BSP — pozostajenam jednak analiza jeszcze jednego zagadnienia, które może być źródłem problemów.
Problem narożników
Niestety zastosowanie prostopadłościanów otaczających nie daje całkowitej pewnościco do skuteczności wykrywania kolizji! Jeśli sprawdzamy, czy którykolwiek z wierz-chołków prostopadłościanu otaczającego nie koliduje ze światem, nie obsługujemy sy-tuacji, w której świat koliduje z prostopadłościanem, chociaż nie koliduje z żadnymz jego wierzchołków (patrz rysunek 11.12).
Na powyższym rysunku obiekt koliduje z ostrym narożnikiem, który nie dotyka żadne-go z wierzchołków prostopadłościanu otaczającego ten obiekt.
Jednym ze sposobów ominięcia tego problemu jest sprawdzanie ewentualnych punktówprzecięcia każdej krawędzi prostopadłościanu otaczającego z wielokątem reprezento-wanym w drzewie BSP. Jeśli którakolwiek z krawędzi przecina wielokąt w drzewie BSP,obiekt jest cofany na oryginalną pozycję. Odpowiednią metodę zaimplementujemy jesz-cze w tym rozdziale. Alternatywnym rozwiązaniem jest tylko nieznaczne wycofywanie
Rozdział 11. ♦ Wykrywanie kolizji 509
Rysunek 11.12.Problemem może być
kolizja obiektu z ostrym
narożnikiem
obiektu i ponowne przeprowadzenie testu na występowanie kolizji. Jeszcze innym roz-wiązaniem jest upewnienie się, że poziomy nie będą projektowane w sposób uniemoż-liwiający wystąpienie tego typu sytuacji. Takie ograniczenia dotyczące poziomów w grzemogą jednak negatywnie wpłynąć na realizm gry i znacznie utrudnić pracę projektan-tom poziomów, dla których stosowanie ostrych narożników (podobnych do tego z po-wyższego przykładu) jest zupełnie naturalne.
Implementacja wykrywania kolizji typu obiekt-świat
Mamy już wszystkie elementy potrzebne do wykrywania kolizji typu obiekt-świat z wy-korzystaniem drzewa BSP. Resztę kodu umieściliśmy na listingu 11.6.
Listing 11.6. Sprawdzanie kolizji ze ścianami (CollisionDetection.java)
���+���������� (,��������� �-����������-��� ��5��������)�$��������7$%�@&����"������ �5�AA���������9$%�@&����"������ ��%!���������������� �&�$����D����$�����,����"������ ,������K��%�@&� ���%#*
���
�������+������,���(��(��������������������������������� ��������� ���� (����������B+G��9����������;����� �,������;�����������������,����������F� ���,�������������� ���(����������������B+GG��(�� �����D����$/��.����������,����0���12����"������ ,��� �������K��%!����0���12� �&���������K� �)��$%���0�����($%#����G��(�� /���B�� ������ ���&���������B�� ��$%#����)�����5�&���������7$%#����)�����(�&���������8$%#����)�������&���������9$%#����)������&���� �����M�����$%#����)��������+���&�E#�����)�$@��������P�(� �$%%�!�����������+���&�B+GG��(�� �G'++'B"NOD'""OKIMN+I."2#����*
510 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
����)������������&���������8$%�?���� �����B�����I����$%�?�����������+��#����)���������&���������8$%�?���� �����K��I����$%#
�������D(���� �����4��(��� ����������������X�������-��������B+GG��(�� �������D����&� ���#����)�����������2���+C�&�P�����6'7O0'"3N#����)��$� ���&E#��>�.MHNM+�� ���#��??%�!��������)�����5.))���&�����.MHNM+Q�R�5#��������)������.))���&�����.MHNM+Q�R�(#��������B+GG��(�� ������&���P���D���S ������ $����"������ �5?5.))��,�����������"������ ��?�.))��,�5?5.))��,��?�.))��,�������,����%#���������)�$�����@&� ���%�!������������)�����5J�&�� ������ �5<5.))��#������������)������J�&�� ������ �(<�.))��#������������)������5�&�$5J<���"������ �5%#������������)��������&�$�J<���"������ ��%#������������)���������+C�&��5��5�?������#���������������D(���� �����4��;����� ������<����������-�������������������������� ��;��� �<��(������4;�;����� ��$����������������������������������� (�������������������%��������������)�$����+C�>�������2���+C�AA����������������$����+C�&&�������2���+C�TT����������������6�6������� $5.))��%�&&�6�6������� $ �5%�TT����������������6�6������� $�.))��%�&&�6�6������� $ ��%%%������������!����������������������D����&�����#����������������������2���+C�&�����+C#������������������������"������ $%���K�$5J,�(,��J%#������������*��������*����*
�����)�$������D����@&� ���%�!�������������� ���)(D����������� $%#����*
�������3�� ������,�4��(-���������;�������������������������$ ���������������(��� ��4 �����%�����5�&���������7$%#������&���������9$%#����<&=#����)��$� ���&E#��>�.MHNM+�� ���#��??%�!��������� �� 5��&��?=#���������)�$ 5��&&��.MHNM+�� ���%�!������������ 5��&�E#��������*�����������34(����������$<=%,��(� �����������F��������� ������������������(��;�(�����(�-(�������������������)�����5.))��=�&�����.MHNM+Q�R�5#��������)������.))��=�&�����.MHNM+Q�R�(#��������)�����5.))��J�&�����.MHNM+Q 5�R�5#��������)������.))��J�&�����.MHNM+Q 5�R�(#
��������B+GG��(�� ������&���P���D���S ������ $������������5?5.))��=,��?�.))��=,�5?5.))��J,��?�.))��J,������������������,����%#
Rozdział 11. ♦ Wykrywanie kolizji 511
���������)�$�����@&� ���%�!������������������ ���)(D����������� $%#��������������������"������ $%���K�$�������������������"������ �5,���������8$%,����"������ ��%#�������������� �����#��������*����*
������ �������D���#*
Na początku w powyższym kodzie testowane jest występowanie punktów przecięciapomiędzy ścianami a czterema ścieżkami, po jednej dla każdego wierzchołka podstawyprostopadłościanu otaczającego. Jeśli algorytm wykryje więcej niż jeden punkt prze-cięcia, zostanie wybrany punkt najbliższy.
Jeśli dwa punkty przecięcia znajdują się w tej samej odległości od obiektu (bryły otacza-jącej), wybierany jest punkt położony bliżej wektora ruchu obiektu. Takie rozwiązanieułatwi nam w dalszej części tego rozdziału implementację przemieszczania się obiektuwzdłuż ściany.
Jeśli zostanie znaleziony i wybrany dokładnie jeden punkt przecięcia, obiekt jest usta-wiany w miejscu kolizji, bezpośrednio przy ścianie, z którą koliduje.
Po wykonaniu tych testów w przedstawionym kodzie sprawdzane jest, czy prostopadło-ścian otaczający obiekt na pewno jest pusty (nie koliduje z ostrymi narożnikami — patrzrysunek 11.12). Jeśli tak się dzieje, obiekt jest przywracany na pierwotną pozycję.
To wszystko — zaimplementowaliśmy właśnie prosty mechanizm wykrywania i obsłu-gi kolizji! Wypróbujmy teraz, jak nasze rozwiązanie działa w praktyce.
Prosty program demonstracyjnywykrywający kolizje
Program demonstracyjny ���������&��� (dołączony do kodów źródłowych opracowa-nych dla tej książki) pokazuje działanie utworzonego do tej pory mechanizmu wykry-wania kolizji. Program bardzo przypomina program '� ��&��� z poprzedniego roz-działu — dodano jedynie mechanizm wykrywania kolizji i zastosowano klasę ������������� ������.
W programie obiekt (gracz) jest zatrzymywany w momencie, gdy dojdzie do ściany;gracz może także wchodzić po schodach na wyższe poziomy. Gracz jest ponadto za-trzymywany, kiedy dojdzie do innego obiektu, np. robota lub skrzyni. Wystrzeliwaneprzez gracza pociski niszczą roboty i — dla uzyskania ciekawszego efektu — wbijająsię w ściany, podłogi, sufity i inne obiekty (zamiast przez nie przelatywać).
512 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
Mechanizm wykrywania kolizji w tym programie działa doskonale, jednak wymaga kil-ku istotnych ulepszeń:
� Kolizja ze ścianą powoduje zablokowanie możliwości ruchu. Takie rozwiązaniebyłoby nie do przyjęcia w trójwymiarowej grze FPP lub TPP, w której graczeoczekują możliwości poruszania się wzdłuż ścian i bezpośrednio przy nich.
� Poruszanie się w górę i w dół po schodach wygląda mało realistycznie, ponieważgracz jest momentalnie przenoszony w górę lub w dół zamiast płynnie pokonywaćkolejne stopnie lub opadać na skutek działania siły grawitacji.
� Gracz nie może przekroczyć małego obiektu na swojej drodze. Wystarczy strzelićw podłogę i spróbować przekroczyć wbity pocisk — jest to niestety niemożliwe.
� Bohater nie może skakać. Nie dotyczy to oczywiście mechanizmu wykrywaniakolizji, ale tego elementu wyraźnie brakuje.
Chyba nas trochę poniosło — przecież celem tego rozdziału jest obsługa kolizji, wróć-my więc do rozwiązywania związanych z tym problemów! Mimo że tak naprawdę tozagadnienie nie jest związane z obsługą kolizji, w tym momencie warto poświęcić tro-chę czasu na zaimplementowanie zarówno skakania, jak i wykrywania kolizji w czasie,gdy obiekt uderza w coś, będąc w powietrzu (podczas skoku).
Obsługa kolizji z przesuwaniem
Kolejnym krokiem jest opracowanie takiego mechanizmu obsługi kolizji, który nie bę-dzie przeszkadzał graczowi — czyli obsługi kolizji zgodnej z oczekiwaniami gracza.
Zamiast blokowania kolidujących obiektów zaimplementujemy ich przesuwanie sięwzględem siebie. Przykładowo, zamiast zatrzymywać gracza wchodzącego na danyobiekt, gracz będzie ten obiekt płynnie omijał. Gracz będzie także mógł się poruszaćwzdłuż ścian oraz przekraczać niewielkie obiekty znajdujące się na podłodze.
W tym podrozdziale zaimplementujemy także kilka prostych elementów lepiej odwzo-rowujących fizyczne zachowania obiektów — możliwe będzie płynne pokonywanieschodów, uwzględnianie siły grawitacji, a także skakanie gracza.
Przesuwanie obiektu wzdłuż innego obiektu
Do tej pory, kiedy następowała kolizja typu obiekt-obiekt, po prostu przywracaliśmyporuszający się obiekt na jego pierwotną pozycję. W efekcie obiekt był momentalnie„odbijany” od statycznego obiektu, z którym kolidował.
Aby to poprawić, należy zapewnić możliwość poruszania się obiektu wzdłuż jednejz krawędzi statycznego obiektu. Logicznym rozwiązaniem jest przesuwanie porusza-jącego się obiektu w taki sposób, by po przebyciu jak najkrótszej drogi wzdłuż obiektustatycznego mógł on swobodnie poruszać się dalej. Oznacza to, że kierunek przesu-wania obiektu jest definiowany za pomocą wektora od środka obiektu statycznego do
Rozdział 11. ♦ Wykrywanie kolizji 513
środka obiektu, który się porusza (patrz rysunek 11.13). Na rysunku widać poruszającysię większy obiekt, który koliduje z mniejszym obiektem statycznym. Większy obiektomija mniejszy obiekt w taki sposób, że oba obiekty są styczne, ale ze sobą nie kolidują.
Rysunek 11.13.Przesuwanie obiektuwzdłuż innego obiektu:poruszający się obiektjest „odpychany”od obiektu statycznego
Długość drogi wzdłuż obiektu statycznego jest różnicą pomiędzy drogą minimalnąa drogą rzeczywistą:
)������� 2����&������'�������?������B������#)���������2���� ��&��� 2����<�������2���#
Oznacza to, że ponieważ wektor łączący środki obu obiektów ma długość ����������,wzór przyjmuje postać:
)����������&�����2���� ����������2���# �����������($����%#
Jeśli zamiast tego chcemy otrzymać tylko odległość podniesioną do kwadratu, wyko-namy instrukcje:
)����������&�$)����%6�����C�$�� 2���+C���������2���+C%�<�=# �����������($����%#
Funkcja obliczająca pierwiastek kwadratowy działa co prawda stosunkowo wolno,jednak trzeba ją wywołać tylko w momencie, gdy obiekt zderza się z innym obiektem,a taka sytuacja nie zdarza się zbyt często.
Przesuwanie obiektów powoduje problemy, kiedy obiekt przemieszczający się wzdłużobiektu statycznego powoduje kolizję ze ścianą lub innym obiektem. W takim przy-padku przesuwany obiekt jest po prostu przenoszony do początkowego położenia, cooznacza, że pozostaje efekt „odbijania” obiektu — gracz musi wówczas zmienić kie-runek ruchu.
Implementacja przesuwania obiektu wzdłuż innego obiektu jest stosunkowo prosta.Cały potrzebny kod umieściliśmy w klasie ������������������$���'������, która jestpodklasą klasy ������������������. Metoda odpowiadająca za taką obsługę kolizji jestprzedstawiona na listingu 11.7.
Listing 11.7. Przesuwanie obiektu wzdłuż innego obiektu (CollisionDetectionWithSliding.java)
�������.��-���������������������.�����'�������������������;�(��������,� ���������������B������(��������,������(��������'�������������.�����'���������������-�4����������������B�����$�������������4���%���������� �������
514 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
�������������� ��� ��.������������ $/��.����������',�/��.����������B,)���������+C,�)������� 2���+C,�0���12����"������ %!���������'� ���)(.������������ $�����B%#
�����)�$�����'���P�(� �$%%�!���������� ���#����*
����)��������+���&������'���B�� ��$%���K��I����$%���Y#����0���12� �����(�&������'���K� �)��$%���0�����($%#
�������Z���������4���,����[� �������������(�� (������)����������'B������&������'���8$%�?������'���B�� ��$%���B�����I����$%#����)����������BK���&������B���8$%�?������B���B�� ��$%���K��I����$%#�����)�$�����'B������?����+���L������BK���TT������BK���?������'���B�� ��$%�������K��I����$%�>������'������I����$%%����!�������������'���"������ $%�(�&�$�����BK���<������'���B�� ��$%�����������B�����I����$%%#���������)�$ �����(�(�>�E%�!�����������������'���Z���� �$)���%#���������������3������ �������-� ����-(����������������������� �����(�(�&�<�E=)#��������*���������� �)���#����*
�����)�$�����'���7$%�@&����"������ �5�AA������'���9$%�@&����"������ ��%����!�����������G����������������-�4��������������������(�� �����������)���������2���P�����&�$)����%6�����C�$�� 2���+C�������+C%�<�=#�����������������K�$�����'���7$%,�E,������'���9$%%#����������������������$�����B���7$%,�E,������B���9$%%#����������������������($����2���P����%#�������������'���"������ $%����$������%#
�����������Z������������������������ ;,���(��F������������ �����-�4 ������������)�$��������D����$�����',����"������ ,�E%�@&� ���%��������!�������������� ���#��������*
���������� �)���#����*
������ ���#*
W powyższym kodzie przesłaniamy metodę ���������������������. Nowa metodaw pierwszej kolejności sprawdza, czy poruszający się obiekt nie może przejść nadobiektem statycznym. Jeśli nie, obiekt jest przesuwany wzdłuż krawędzi obiektu statycz-nego. Jeśli przesuwanie powoduje kolizję ze ścianą, obiekt jest przywracany na pier-wotną pozycję.
Rozdział 11. ♦ Wykrywanie kolizji 515
Skoro mówimy o kolizjach ze ścianami, warto się zastanowić, jak zaimplementowaćporuszanie się obiektu wzdłuż ściany.
Przesuwanie obiektu wzdłuż ściany
Obsługa płynnego ruchu obiektu wzdłuż ściany jest z pozoru skomplikowanym zada-niem, jednak w rzeczywistości wymaga jedynie zastosowania kilku prostych obliczeńmatematycznych. Jeśli znamy docelowe położenie obiektu (miejsce, do którego obiektdotarłby, gdyby na jego drodze nie było ściany), możemy łatwo znaleźć miejsce, w któ-rym obiekt powinien się znaleźć, poruszając się wzdłuż ściany (patrz rysunek 11.14).
Rysunek 11.14.Przesuwanie obiektu
wzdłuż ściany:
obiekt porusza się
wzdłuż ściany
Na powyższym rysunku szarym odcinkiem oznaczyliśmy prostą prostopadłą do ściany.Jeśli znamy długość tej prostej, możemy łatwo obliczyć docelowe miejsce poruszają-cego się obiektu. Mamy do czynienia z prostym trójkątem prostokątnym. Rozważmywektor prowadzący do miejsca kolizji od docelowego położenia obiektu:
������K�$������7,�E,�������9%# �����������$����7,�E,�����9%#
Długość interesującego nas odcinka jest wówczas iloczynem skalarnym tego wektorai wektora prostopadłego do wielokąta pełniącego rolę ściany:
)������ ����&� ������2��G�����$�������H����$%%#
Możemy teraz obliczyć położenie punktu docelowego obiektu poruszającego się wzdłużściany
)���������7�&�����7�?�� ����?��������H����$%�5#)���������9�&�����9�?�� ����?��������H����$%��#
Tak wygląda rozwiązanie tego problemu. Cały kod (włącznie z dodatkowymi instruk-cjami warunkowymi) obsługujący przesuwanie obiektu wzdłuż ściany znajduje się nalistingu 11.8.
516 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
Listing 11.8. Przesuwanie obiektu wzdłuż ściany (CollisionDetectionWithSliding.java)
�� ���0���12��������&� ��0���12$%#�� ���0���12����� ��"������ �&� ��0���12$%#
���
�������+������,���(������������ ���������������� ������ ���� (�������������B+G��9����������;����� �,�����������(��������������,�������������F� ���,������������ ������������4�� ;����� ;��Z�����������(�(������������,������������������������-�4����� (����������,���(� ������(������;����� ���������Z��������������������-�4����� (� ���;������ �����������,�������������(���� (� ������;������ ;����(�������������B+GG��(�� �����D����$/��.����������,�0���12����"������ ,��� �������K��%!
����)���������7�&���������7$%#����)���������9�&���������9$%#
����B+GG��(�� ������&���������D����$�����,����"������ ,������K��%#�������Z�����(�(��������������������������� ������(��-V�����)�$�����@&� ����TT���������K� �)��$%���6� � �$%%�!��������)�����������7�&���������7$%#��������)�����������9�&���������9$%#
�����������S����( ������ (���������������-���������� (����� ���������;�������������������������������������K�$������7,�E,�������9%#����������������������$����7,�E,�����9%#��������)������ ����&����������2��G�����$�������H����$%%#
��������)���������7�&�����7�?�� �������������H����$%�5#��������)���������9�&�����9�?�� �������������H����$%��#
����������������"������ $%���K�$����7,���������8$%,�����9%#������������ ��"������ ���K�$���"������ %#�����������"������ ���K�$������7,����"������ �(,�������9%#
�����������34(��� ����������� �������� �������������������-�4����� (���������G��(�� /���B�� ������ ���&���������B�� ��$%#��������)��������� ��M������&���� �����M�����$%#����������� �����M�����$���� ��M�����<=%#
�����������+�������(������� ��������������������������-�4����� (���������B+GG��(�� �����J�&���������D����$�����,����"������ ,������K��%#
�����������G�(��F���� �� ������(������������"������ ���K�$���� ��"������ %#����������� �����M�����$���� ��M�����%#
���������)�$����J�@&� ���%�!��������������������"������ $%���K�$����������������������7,���������8$%,�������9%#�������������� �����J#��������*����*
������ �����#*
Rozdział 11. ♦ Wykrywanie kolizji 517
W powyższym kodzie metoda �����$������ przykrywa metodę zdefiniowaną w klasie������������������. Metoda odpowiada za obsługę ruchu wzdłuż ściany oraz spraw-dzanie, czy po wykonaniu tego ruchu nie występują inne kolizje z dowolnymi innymiścianami. Jeśli taka kolizja ma miejsce, obiekt jest cofany do punktu, w którym nastą-piła kolizja.
Oczywiście zawsze możemy wyłączyć mechanizm przesuwania obiektu wzdłuż ściany.Przykładowo metody obsługujące kolizje obiektów reprezentujących pociski powinnypowodować natychmiastowe zatrzymywanie pocisku po uderzeniu w ścianę, podłogęlub sufit:
������� ���� ���)(D����������� $%�!������ �)�����0�����($%���K�$E,E,E%#*
������� ���� ���)(P����������� $%�!������ �)�����0�����($%���K�$E,E,E%#*
������� ���� ���)(���� ��������� $%�!������ �)�����0�����($%���K�$E,E,E%#*
Za pomocą powyższych metod uzyskujemy efekt „wbijania” się pocisków w ściany i inneobiekty, co oznacza, że możemy emulować omawianą wcześniej technikę obsługi kolizji.
Zaimplementowaliśmy już przemieszczanie się obiektów wzdłuż obiektów statycznychi ścian. Naszym następnym celem jest płynne poruszanie się obiektów na schodachi uwzględnienie siły grawitacji.
Grawitacja i płynny ruch na schodach(przesuwanie obiektu wzdłuż podłogi)
Kolejnym powszechnie stosowanym efektem jest umożliwienie graczowi i innym obiek-tom występującym w grze płynne poruszanie się na schodach. Bez odpowiedniej ob-sługi takiego ruchu gracz będzie w nienaturalny sposób skakał, chodząc po schodach(tak było w naszym pierwszym programie demonstrującym mechanizm wykrywaniakolizji), ponieważ położenie obiektu w osi y będzie się z każdym kolejnym stopniemskokowo zmieniało.
Także kiedy gracz będzie schodził z wyższego poziomu na niższy, będzie momentalniespadał na odpowiednią wysokość zamiast płynnie spadać na skutek działania grawitacji.
Wpływ siły grawitacji na obiekty w grze będziemy obsługiwali tak samo, jak w roz-dziale 5., gdzie z czasem zwiększała się szybkość opadania obiektu. Siłę grawitacji mo-żemy stosować dla obiektu, który znajduje się na większej wysokości niż znajdującasię pod nim podłoga.
Dokładnie odwrotnie jest w przypadku wchodzenia gracza po schodach: jeśli obiekt znaj-duje się na mniejszej wysokości niż podłoga pod nim, wówczas należy zastosować przy-spieszenie w górę.
518 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
Obsługę wszystkich własności fizycznych związanych z ruchem obiektu umieściliśmyw klasie ������� (patrz listing 11.9). To oczywiście dopiero początek implementacji tychzjawisk — w przyszłości dodamy kolejne elementy.
Listing 11.9. Grawitacja i wchodzenie po schodach (plik Physics.java)
�������2��(�� ���(����� ������������� �������� ��������� �����������;�����������������)� ���)�����2NP'3"KO/M'0SK8O'��N"�&�<�EEJ)#
�������2��(�� ���(����� ����������������������������� �������� ������������ �����������;�����������������)� ���)�����2NP'3"KO+�..KO'��N"�&��EEY)#
�� ���)������� ��('���#�� ���)����������'���#�� ���0���12� �����(�&� ��0���12$%#
�������+��������(����� ���������(� ���������� ��������������(����/��.�������-��������,����(��� ;-��������� ������������������������� ��������(/� ��($/��.����������,��� �������K��%�!���� �����(���K�$E,��� ��('�����������K��,�E%#������������K� �)��$%����0�����($ �����(%#*
�������+��������(����� �������������������������������������� �����������������(�/��.�������-��������,����(��� ;-��������� ���������������������������� ���������3�$/��.����������,��� �������K��%�!���� �����(���K�$E,������'�����������K��,�E%#������������K� �)��$%����0�����($ �����(%#*
Znacznie bardziej skomplikowanym zadaniem jest uzyskanie wiedzy o tym, kiedy nale-ży stosować zaimplementowane powyżej efekty w różnych sytuacjach. Przykładowodziałania siły grawitacji nie powinniśmy uwzględniać w przypadku latających obiektów.Nie powinniśmy też obsługiwać płynnego wchodzenia po schodach w przypadku, gdygracz znajduje się w powietrzu, lecz należy ten efekt stosować w przypadku podska-kującego obiektu (do samego skakania przejdziemy za chwilę).
Wszystkie takie sytuacje obsługujemy w kodzie przedstawionym na listingu 11.10.
Listing 11.10. Sprawdzanie podłogi i sufitu (CollisionDetectionWithSliding.java)
�������+������,���(��������������������-��;�����)��������34(����������������P���I����$%��������������I����$%
Rozdział 11. ♦ Wykrywanie kolizji 519
����������(��� ������������)� ���;�(������-��������)����+�����������(����� ��������������������� �����;������������������������-( ���(����� ���������������������� �����;�������� ���(��������� ������ �4��( �����(�����F�������-����$������(��� ���)�����-( ��������� ��������������%���������� ��������P���' ����� �$/��.����������,��� �������K��%!����)�����)���I�����&���������P���I����$%#����)��������I�����&������������I����$%#����)�����������I�����&���������B�� ��$%���B�����I����$%#����)��������I�����&���������B�� ��$%���K��I����$%#����0���12� �&���������K� �)��$%���0�����($%#����G�(�������(�����&�G�(�������S ��� �$%#
�������+������,���(������������ �����-���������)�$��������8$%�?�������I�����&&�)���I����%�!���������)�$ �(�>�E%�!������������ �(�&�E#��������*����*�������+������,���(������� ��� ������������ �4�������������-������������)�$��������8$%�?�������I�����>�)���I����%�!
���������)�$@��������P�(� �$%%�!���������������Z���������V�������������)�$ �(�>�E%�!���������������������� ���)(P����������� $%#���������������� �(�&�E#������������������������"������ $%�(�&�)���I�����<�������I����#������������*����������������)�$@��������Z���� �$%%�!������������������(����������3�$�����,������K��%#������������*��������*�����������!������������������ ���)(P����������� $%#������������ �(�&�E#��������������������"������ $%�(�&�)���I�����<�������I����#��������*����*�������+������,���(������� �����������)�����������)�$��������8$%�?����I�����L����I����%�!�������������� ���)(���� ��������� $%#���������)�$ �(�L�E%�!������������ �(�&�E#��������*����������������"������ $%�(�&����I�����<����I����#���������)�$@��������P�(� �$%%�!��������������(���������(/� ��($�����,������K��%#��������*����*�������H������-��;V�������!���������)�$@��������P�(� �$%%�!���������������9���(��������������������������$���������������������������%�
520 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
�������������)�$ �(�L�E�TT�@��������Z���� �$%%�!���������������� �(�&�E#������������������������"������ $%�(�&�)���I�����<�������I����#������������*���������������!������������������(���������(/� ��($�����,������K��%#������������*��������*����**
Powyższy fragment kodu przykrywa zdefiniowaną w klasie ������������������ me-todę �����"����#�����������. Pozostało nam już tylko zaimplementowanie skakania(głównie dla zabawy).
Skakanie
Skakanie powinno wyglądać bardzo podobnie, jak mechanizm zrealizowany w roz-dziale 5. — należy po prostu właściwie obsłużyć wektor skierowany w górę. Począt-kowa wartość tego wektora zmniejsza się na skutek działania siły grawitacji.
W niektórych sytuacjach trzeba jednak określić, jak wysoko dany obiekt może skoczyć.Odpowiednie równanie prezentujemy na rysunku 11.15.
Rysunek 11.15.Znajdowanie szybkości
skoku dla określonej
wysokości
Na rysunku 11.15 szybkość skoku (v) można wyznaczyć na podstawie wysokościskoku (y – y0) oraz przyspieszenia ziemskiego (a). To standardowe równanie dla szyb-kości i przyspieszenia jest powszechnie stosowane w podręcznikach do fizyki.
Możemy teraz dodać do naszej klasy ������� kilka nowych metod implementującychskakanie (patrz listing 11.11).
Listing 11.11. Skakanie (Physics.java)
�������3������������� ����������/��.��������������������,����(�������4��������������������� ������� ;��(�����F��D(��-��������������Z���0�����($%,����������������(����F��������������;�)� ��������6�����C�$%�
Rozdział 11. ♦ Wykrywanie kolizji 521
��������� ��������K�I����$/��.����������,�)���������I����%�!��������$�����,���Z���0�����($����I����%%#*
�������3������������ ;���(����F��������� ������������/��.����������������� ����(���������������������� ��������$/��.����������,�)���������0�����(%�!���� �����(���K�$E,�����0�����(,�E%#������������K� �)��$%���0�����($%�(�&�E#������������K� �)��$%����0�����($ �����(%#*
�������9���������;����;���(����F������������ ;�������;� �������������� ���(��������$���������� � �����4;������������%�����D(���(������������� �����)� �����6�����C�$%����������)�������Z���0�����($)���������I����%�!�������34(�������������(�����������(����� ��V� � �&�<J����$(<(E%�������$ �������(������;������,��������(���,�(<(E��������(��� ���(��%������ �$)����%6�����C�$<J��� ��('��������I����%#*
Powyższe metody umożliwiają nam zarówno znalezienie prędkości początkowej (w pio-nie) potrzebnej do osiągnięcia danej wysokości (w obliczeniach wykorzystujemy wartośćprzyspieszenia ziemskiego), jak i obsługę samego skoku.
Program demonstracyjnyobsługujący kolizje z przesuwaniem
Zakończyliśmy omawianie zagadnień związanych z wykrywaniem kolizji. W kodachopracowanych dla tej książki znajduje się klasa ���������&���'������, która różni sięod wcześniejszego programu demonstracyjnego jedynie implementacją obsługi ruchuwzdłuż innych obiektów. Oznacza to, że w jednym programie zawarliśmy obsługę ru-chu gracza wzdłuż ścian, obsługę ruchu gracza wzdłuż innych obiektów, przekraczaniemałych obiektów, wchodzenie na obiekty, płynne poruszanie się po schodach, stosowa-nie siły grawitacji i podskakiwanie.
Efektem ubocznym zaproponowanego rozwiązania jest możliwość stawania na poci-skach. Ponieważ pociski wbijają się w ściany, możesz wystrzelić taką ich liczbę, by„narysować” z nich dodatkowy poziom przy samej ścianie. Następnie możesz wejśćna ten nietypowy poziom!
522 Część II ♦ Grafika trójwymiarowa i zaawansowane techniki programowania gier
Oczywiście jest to tylko jeden (zapewne nie najbardziej realistyczny) ze sposobówobsługi kolizji pocisków. Zwykle będziemy starali się zapewnić zniszczenie (nie wbija-nie się) pocisków niezależnie od tego, w co trafiają.
Rozszerzenia
Opracowany przez nas mechanizm wykrywania i obsługi kolizji całkiem nieźle spraw-dza się w praktyce, stworzone rozwiązanie nie jest jednak doskonałe i wymaga dalszychulepszeń. Oto kilka pomysłów na przyszłe rozszerzenia:
� Implementacja drzew sfer, umożliwiających bardziej precyzyjne wykrywaniekolizji typu obiekt-obiekt.
� Wykonywanie dodatkowych testów pozwalających określić, czy obiekt nie przebyłpomiędzy klatkami na tyle dużej odległości, by możliwe było wystąpienie kolizjipomiędzy punktem startowym a punktem docelowym.
� Umożliwienie graczom skradania i czołgania się, co pozwoli im na wchodzeniedo niższych pomieszczeń.
� Implementacja wahań kamery oddających ruch głowy gracza podczas chodzeniai biegania.
Podsumowanie
Mechanizm wykrywania kolizji jest nieodłącznym elementem niemal każdej współcze-snej gry (dwu- i trójwymiarowej).
Na początku tego rozdziału omówiliśmy zagadnienie izolowania obiektów za pomocąsiatki i — tym samym — ograniczania liczby niezbędnych testów na występowaniekolizji. Następnie skupiliśmy się na różnych mechanizmach wykrywania kolizji, opartychna sferach otaczających, drzewach sfer, walcach otaczających i prostopadłościanachotaczających. Zaimplementowaliśmy algorytmy wykrywania kolizji zarówno z innymiobiektami, jak i ze ścianami, podłogami oraz sufitami reprezentowanymi w drzewie BSP.Zaimplementowaliśmy także lepszy mechanizm obsługi kolizji, który umożliwił gra-czom (i innym obiektom) poruszanie się wzdłuż krawędzi innych obiektów, ścian orazpo schodach. Na końcu, w celu zwiększenia realizmu gry, dodaliśmy wpływ siły gra-witacji i możliwość skakania.
Program demonstracyjny umożliwia niszczenie robotów, co nie jest jednak zbyt trud-nym zadaniem. Nad utrudnieniem gry będziemy pracować w kolejnym rozdziale: do-damy naszym przeciwnikom sztuczną inteligencję, dzięki czemu gra stanie się znacz-nie ciekawsza.