Systemy wirtualnej rzeczywistości. Sterowanie i wykrywanie kolizji

Podobne dokumenty
Systemy wirtualnej rzeczywistości. Komponenty i serwisy

Rozdział 4 Komponenty gry na przykładzie prostopadłościanu

Programowanie telefonów z Windows Phone 7, cz. 3

Systemy wirtualnej rzeczywistości. Podstawy grafiki 3D

Gry Komputerowe Laboratorium 3. Organizacja obiektów sceny Kolizje obiektów. mgr inż. Michał Chwesiuk 1/20. Szczecin, r

Sieciowe Technologie Mobilne. Laboratorium 2

Czym jest wykrywanie kolizji. Elementarne metody detekcji kolizji. Trochę praktyki: Jak przygotować Visual Studio 2010 do pracy z XNA pod Windows

Mechanizm dziedziczenia

Wydział Elektryczny. Katedra Telekomunikacji i Aparatury Elektronicznej. Konstrukcje i Technologie w Aparaturze Elektronicznej.

Zaawansowana Grafika Komputerowa

BLENDER- Laboratorium 1 opracował Michał Zakrzewski, 2014 r. Interfejs i poruszanie się po programie oraz podstawy edycji bryły

Unity 2D - prosta gra

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Zad. 3: Rotacje 2D. Demonstracja przykładu problemu skończonej reprezentacji binarnej liczb

Zad. 7: Sterowanie robotami mobilnymi w obecności przeszkód

Zad. 4: Rotacje 2D. 1 Cel ćwiczenia. 2 Program zajęć. 3 Opis zadania programowego

Instrukcja do zajęć (całość)

Programowanie obiektowe

Zad. 6: Sterowanie robotem mobilnym

Gry Komputerowe - laboratorium 2. Kamera FPP / TPP. mgr inż. Michał Chwesiuk 1/11. Szczecin, r

Programowanie obiektowe

Unity 3D - pierwsze skrypty

Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Zad. 6: Sterowanie robotami mobilnymi w obecności przeszkód

FINCH PONG. Realizator: Partner: Patronat:

Gry Komputerowe Interaktywna kamera FPP

Grafika Komputerowa Materiały Laboratoryjne

Tworzenie gier na urządzenia mobilne

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

Mechanizm dziedziczenia

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Symulacje komputerowe

Trajektoria rzuconego ukośnie granatu w układzie odniesienia skręcającego samolotu

Temat: Transformacje 3D

Deklaracja i definicja metod, zwracanie wartości z metod, przekazywania parametrów do metod

OpenGL : Oświetlenie. mgr inż. Michał Chwesiuk mgr inż. Tomasz Sergej inż. Patryk Piotrowski. Szczecin, r 1/23

1. Prymitywy graficzne

Zad. 6: Sterowanie dronami w obecności przeszkód

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania

Grafika Komputerowa Wykład 4. Synteza grafiki 3D. mgr inż. Michał Chwesiuk 1/30

IRONCAD. TriBall IRONCAD Narzędzie pozycjonujące

Informatyka II. Laboratorium Aplikacja okienkowa

Laboratorium 1. Część I. Podstawy biblioteki graficznej OpenGL.

Przykładowa dostępna aplikacja w Visual Studio - krok po kroku

Klasy i obiekty cz II

Rozdział 4 KLASY, OBIEKTY, METODY

Przekształcenia geometryczne. Dorota Smorawa

Budowa i generowanie planszy

Programowanie telefonów z Windows Phone 7, cz. 5

Rysunek 1: Okno timeline wykorzystywane do tworzenia animacji.

Podstawy Programowania C++

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 3

Zad. 5: Sterowanie robotem mobilnym

WIZUALIZACJA I STEROWANIE ROBOTEM

Programowanie strukturalne i obiektowe. Funkcje

Politechnika Poznańska, Instytut Informatyki, SUM-TWO

8. Wektory. Przykłady Napisz program, który pobierze od użytkownika 10 liczb, a następnie wypisze je w kolejności odwrotnej niż podana.

Zad. 5: Sterowanie dronem

Spadające jabłuszka. licencja CC-BY-SA Uznanie autorstwa Na tych samych warunkach 3.0 Polska. Strona 51

3. Macierze i Układy Równań Liniowych

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

4. Funkcje. Przykłady

Zad. 10: Sterowanie manipulatorem cz. 2 i 3

Tworzenie nowego rysunku Bezpośrednio po uruchomieniu programu zostanie otwarte okno kreatora Nowego Rysunku.

W powyższym kodzie utworzono wyliczenie dni tygodnia.

Tak przygotowane pliki należy umieścić w głównym folderze naszego programu. Klub IKS

Strzelanka dla dwóch graczy

Edytor tekstu MS Word podstawy

Wprowadzenie do UML, przykład użycia kolizja

PARADYGMATY PROGRAMOWANIA Wykład 4

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Rozdział 6 Cienie rzucane. Mieszanie kolorów

Programowanie II. Lista 3. Modyfikatory dostępu plik TKLientBanku.h

Badanie zależności położenia cząstki od czasu w ruchu wzdłuż osi Ox

Dokąd on zmierza? Przemieszczenie i prędkość jako wektory

Symulacja samochodu z kamerą stereowizyjną. Krzysztof Sykuła 15 czerwca 2007

Studia Podyplomowe Grafika Komputerowa i Techniki Multimedialne, 2017, semestr II Modelowanie 3D - Podstawy druku 3D. Ćwiczenie nr 4.

Unity 3D - własny ekran startowy i menu gry

Języki i techniki programowania Ćwiczenia 2

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Czym są właściwości. Poprawne projektowanie klas

Ping-Pong. Gra dla dwóch graczy.

Diagramy UML, przykład problemu kolizji

Scenariusz lekcji Ozobot w klasie: Tabliczka mnożenia

Lekcja 5 - PROGRAMOWANIE NOWICJUSZ

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

Język ludzki kod maszynowy

Języki programowania imperatywnego

Gry Komputerowe Laboratorium 4. Teksturowanie Kolizje obiektów z otoczeniem. mgr inż. Michał Chwesiuk 1/29. Szczecin, r

Sieciowe Technologie Mobilne. Laboratorium 4

Część 4 życie programu

Algorytm grupowania danych typu kwantyzacji wektorów

Zadanie polega na zbudowaniu i wyświetleniu przykładowej animowanej sceny przedstawiającej robota spawalniczego typu PUMA.

Interfejsy i klasy wewnętrzne

Kompletna dokumentacja kontenera C++ vector w -

Zastosowania Robotów Mobilnych

Grafika 3D program POV-Ray

Animowana grafika 3D Laboratorium 1

Transkrypt:

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych Systemy wirtualnej rzeczywistości Laboratorium Sterowanie i wykrywanie kolizji Wstęp: W czwartej części przedstawione zostaną mechanizmy obsługi urządzeń wejściowych w XNA. Zrealizowane zostanie sterowanie czołgiem. Zostaną również omówione i zaimplementowane techniki wykrywania kolizji gracza z terenem i przeszkodami. 1. Sterowanie czołgiem Pisanie obsługi sterowania zaczniemy od obracania korpusu i wieżyczki. Przechodzimy do metody UpDate klasy Gracz. Przede wszystkim musimy pobrać informacje o stanie klawiatury. Obiektem reprezentującym klawiaturę jest Keyboard, a informacje o aktualnym jej stanie zwraca metoda GetState w formie obiektu typu KeyboardState: KeyboardState klawiatura = Keyboard.GetState(); Teraz możemy sprawdzić czy został naciśnięty dany klawisz i zmienić odpowiednio rotacje korpusu i wieżyczki. Ponieważ metoda UpDate może być wywoływana z różną częstotliwością prędkość obracania uzależniamy od czasu jaki miną od poprzedniego zaktualizowania. Z pomocą przychodzi nam parametr wejściowy metody UpDate. Jest to zmienna typu GameTime, która zawiera wiele przydatnych informacji na temat czasu gry. Nas interesuje czas od ostatniego wywołania metody UpDate w milisekundach. Dodatkowo regulujemy prędkość obrotu mnożąc czas razy współczynnik prędkości. // korpus if (klawiatura.iskeydown(keys.a)) rotacjakorpusu += gametime.elapsedgametime.milliseconds * 0.0016f; if (klawiatura.iskeydown(keys.d)) rotacjakorpusu -= gametime.elapsedgametime.milliseconds * 0.0016f; 1

// wiezyczka if (klawiatura.iskeydown(keys.left)) rotacjawiezyczki += gametime.elapsedgametime.milliseconds * 0.004f; if (klawiatura.iskeydown(keys.right)) rotacjawiezyczki -= gametime.elapsedgametime.milliseconds * 0.004f; Jeśli teraz skompilujemy naszą grę będziemy już mogli kontrolować obrót korpusu i wieżyczki czołgu. Przyszła kolej na poruszanie się do przodu i do tyłu. Ponieważ w dalszej części dodamy obsługę kolizji z innymi obiektami na scenie dla uproszczenia umieścimy kod poruszania się czołgu w metodzie UpDate klasy głównej, a nie klasy Gracz. Zaczynamy od pobrania stanu klawiatury: KeyboardState klawiatura = Keyboard.GetState(); Następnie sprawdzamy czy został wciśnięty odpowiedni klawisz: if (klawiatura.iskeydown(keys.w) klawiatura.iskeydown(keys.s)) Zmianę pozycji czołgu uzyskamy dodając do wektora pozycji odpowiedni wektor przesunięcia. Aby go wyznaczyć musimy najpierw ustalić jego kierunek. Chcielibyśmy aby nasz czołg poruszał się do przodu lub do tyły. Obliczamy zatem macierz obrotu korpusu, a następnie wykorzystujemy ją do obrócenia wektora [0.0, 0.0, -1.0] (wektor ten reprezentuje przód czołgu bez uwzględnienia rotacji, jest dostępny jako stała Vector3.Forward). Efektem będzie wektor znormalizowany (o długości 1) skierowany w stronę, w którą zwrócony jest czołg. Vector3 kierunek = Vector3.Transform(Vector3.Forward, Matrix.CreateRotationY(gracz.Rotacja)); Skoro wiemy już po jakiej linii będzie poruszał się gracz wystarczy przesunąć go wzdłuż tej linii w przód lub w tył o odpowiednią ilość jednostek. Ponownie wykorzystamy czas, który minął od ostatniej aktualizacji oraz pewien współczynnik szybkości. Nasz odwrócony wektor mnożymy razy otrzymany skalar i aktualizujemy pozycję gracza. kierunek *= gametime.elapsedgametime.milliseconds * 0.008f; Vector3 nowapozycja = gracz.pozycja; if (klawiatura.iskeydown(keys.w)) 2

nowapozycja += kierunek; if (klawiatura.iskeydown(keys.s)) nowapozycja -= kierunek; gracz.pozycja = nowapozycja; 2. Śledzenie czołgu Chcielibyśmy żeby nasza kamera śledziła czołg gdy będziemy nim poruszać. Dlatego po obliczeniu nowej pozycji gracza uaktualniamy również cel kamery: kamera.cel = nowapozycja; 3. Kolizje Zagadnienie kolizji w grach komputerowych jest bardzo szerokie i zostanie przedstawione jedynie w podstawowym zakresie. Jest wiele metod wykrywania kolizji miedzy obiektami ale wszystkie sprowadzają się do określenia czy dane dwa obiekty się przenikają (np. gracz nie może przejść przez ścianę). Dokładne algorytmy sprawdzania kolizji bazują na analizie wzajemnego położenia poszczególnych trójkątów siatek badanych obiektów (w przypadku bardzo dynamicznych symulacji stosuje się również analizę trajektorii obiektów). Takie dokładne sprawdzanie wymaga oczywiście stosunkowo dużych nakładów obliczeniowych. Należy pamiętać, że z reguły te obliczenia wykonuje się w każdej klatce symulacji. Zakładając, że na scenie jest wiele skomplikowanych obiektów, a sprawdzenie kolizji należy przeprowadzić dla każdej możliwej pary tych obiektów, wymagane jest stosowanie technik optymalizacji. Jedną z nich jest uproszczenie skomplikowanych siatek do postaci prostych brył (np. sześcian, kula), dla których obliczenie kolizji jest proste i szybkie. Dopiero jak nastąpi kolizja dla brył uproszczonych stosuje się dokładniejsze algorytmy w celu weryfikacji. Właśnie takie uproszczone sprawdzanie wykorzystamy w tworzonej aplikacji. XNA posiada podstawowe mechanizmy sprawdzania kolizji opisaną wyżej metodą. Siatkę można opisać sześcianem lub kulą, a klasy reprezentujące te bryły to odpowiednio BoundingBox i BoundingSphere. 3.1 Ograniczenie poruszania sie do terenu Najpierw zajmiemy się ograniczeniem obszaru poruszania się do wygenerowanego terenu. Nasz teren jest kwadratem zatem idealnym sposobem reprezentacji przestrzeni, po której może poruszać się gracz, będzie prostopadłościan. Dodajemy więc zmienną typu BoundingBox do klasy Teren: BoundingBox szescian; 3

Inicjujemy ją w konstruktorze: szescian = new BoundingBox(new Vector3(-rozmiar, -rozmiar, -rozmiar), new Vector3(rozmiar, rozmiar, rozmiar)); Na koniec udostępnimy ją poprzez właściwość: public BoundingBox Szescian get return szescian; Teraz potrzebna nam jeszcze bryła opisująca czołg. Jego kształt jest bardziej nieregularny i możemy nim obracać więc do jego reprezentacji użyjemy kuli. Przechodzimy do klasy gracza i deklarujemy zmienną: BoundingSphere sfera; Podobnie jak w przypadku terenu inicjujemy ją w konstruktorze. Każda siatka w modelu ma już swoją kulę stworzoną na podstawie wierzchołków. Do reprezentacji naszego czołgu wykorzystamy sferę korpusu i odpowiednio ją przeskalujemy: sfera = new BoundingSphere(); sfera = model.meshes["korpus"].boundingsphere; sfera = sfera.transform(matrix.createscale(2.0f * rozmiar)); Na koniec udostępniamy ją poprzez właściwość: public BoundingSphere Sfera get return sfera; Pozostało jeszcze dodać sprawdzanie czy gracz próbuje wyjechać poza teren. Zmodyfikujemy zatem metodę UpDate klasy głównej. Po wyznaczeniu kierunku i obliczeniu nowej pozycji czołgu ale przed jej aktualizacją sprawdzimy czy nowe położenie gracza nie wykracza poza dozwolony obszar. Pobieramy sferę opisującą czołg. Przesuwamy ją w miejsce nowego położenia gracza poprzez transformację translacji. Pobieramy również sześcian opisujący teren. 4

bool kolizja = false; BoundingSphere sfera = gracz.sfera; sfera = sfera.transform(matrix.createtranslation(nowapozycja)); BoundingBox szescian = teren.szescian; Do sprawdzenia wzajemnej korelacji pomiędzy dwiema bryłami wykorzystujemy metodę Contains. Metoda ta zwraca zmienną typu ContainmentType, która określa czy dana bryła zawiera się, przecina lub jest poza inną bryłą. W naszym przypadku interesuje nas aby bryła czołgu zawierała się w bryle terenu. Jeśli nie, następuje kolizja. if (szescian.contains(sfera)!= ContainmentType.Contains) kolizja = true; Jeśli nie wystąpiła kolizja aktualizujemy położenie gracza: if (!kolizja) gracz.pozycja = nowapozycja; kamera.cel = nowapozycja; 3.2 Kolizje z przeszkodami Gracz nie może już wyjechać poza teren. Dodamy teraz przeszkody w postaci prostych skrzynek. Tworzymy nowy komponent i nadajemy mu nazwę Przeszkoda. Zmieniamy dziedziczenie na DrawableGameComponent. Siatkę skrzynki będziemy przechowywać, podobnie jak siatkę czołgu, w zmiennej typu Model. Ponadto potrzebujemy również informacji o pozycji w scenie i rozmiarze, oraz bryłę opisującą, którą będzie sześcian. Deklarujemy więc odpowiednie zmienne: Vector3 pozycja; float rozmiar; Model model; BoundingBox szescian; W konstruktorze inicjujemy zmienne: public Przeszkoda(Game game, Model model, Vector3 pozycja, float rozmiar) : base(game) this.model = model; this.pozycja = pozycja; this.rozmiar = rozmiar; 5

szescian = new BoundingBox(new Vector3(-rozmiar + pozycja.x, pozycja.y, -rozmiar + pozycja.z), new Vector3(rozmiar + pozycja.x, pozycja.y + 2 * rozmiar, rozmiar + pozycja.z)); Rysowanie przeszkody realizujemy analogicznie do rysowania czołgu: public override void Draw(GameTime gametime) GraphicsDevice urzadzenie = (GraphicsDevice)Game.Services.GetService(typeof(GraphicsDevice)); Kamera kamera = (Kamera)Game.Services.GetService(typeof(Kamera)); Matrix[] transformacje = new Matrix[model.Bones.Count]; model.copyabsolutebonetransformsto(transformacje); foreach (ModelMesh mesh in model.meshes) foreach (BasicEffect effect in mesh.effects) effect.enabledefaultlighting(); effect.projection = kamera.projekcja; effect.view = kamera.widok; effect.world = transformacje[mesh.parentbone.index] * Matrix.CreateScale(rozmiar) * Matrix.CreateTranslation(pozycja); mesh.draw(); base.draw(gametime); Na koniec udostępniamy zmienną szescian poprzez właściwość: public BoundingBox Szescian get return szescian; Stworzymy teraz dwie przeszkody. Przechodzimy do klasy głównej gry. Dodajemy do projektu plik przeszkoda.fbx. Deklarujemy zmienną typu Model oraz dwie zmienne typu Przeszkoda. Model przeszkoda; Przeszkoda przeszkoda1; Przeszkoda przeszkoda2; 6

Następnie w metodzie LoadContent wczytujemy model przeszkody z dodanego właśnie pliku: przeszkoda = Content.Load<Model>("przeszkoda"); Do listy komponentów dodajemy dwie przeszkody: przeszkoda1 = new Przeszkoda(this, przeszkoda, new Vector3(-6.0f, 0.0f, -3.0f), 0.9f); Components.Add(przeszkoda1); przeszkoda2 = new Przeszkoda(this, przeszkoda, new Vector3(2.5f, 0.0f, 2.5f), 1.2f); Components.Add(przeszkoda2); Pozostało jeszcze obsłużyć kolizje czołgu z przeszkodą. W metodzie UpDate dodamy sprawdzenie czy gracz najechał na którąś z przeszkód. Tym razem zależy nam aby czołg znajdował się poza bryłą przeszkody. Zatem kolizja wystąpi kiedy bryła gracza przetnie lub zawrze się w bryle przeszkody. szescian = przeszkoda1.szescian; if (szescian.contains(sfera)!= ContainmentType.Disjoint) kolizja = true; szescian = przeszkoda2.szescian; if (szescian.contains(sfera)!= ContainmentType.Disjoint) kolizja = true; Rys. 1 prezentuje przykładowy zrzut ekranu z gotowej aplikacji. Rys. 1 - Przykładowy zrzut ekranu z gotowej aplikacji 7

4. Zadanie dodatkowe Wykorzystując poznane mechanizmy należy dodać możliwość wystrzelenia z lufy pocisku. Do instrukcji został dołączony plik kula.fbx, który zawiera odpowiedni model 3D. Po naciśnięciu przez gracza odpowiedniego przycisku powinien nastąpić wystrzał. Dodatkowo należy sprawdzić kolizje pocisku z przeszkodami i w przypadku trafienia w przeszkodę należy ją usunąć i losowo wygenerować nową (uwzględniając położenie czołgu nowa przeszkoda nie powinna przenikać ani czołgu ani drugiej przeszkody). 8