W poprzedniej notce przedstawiłem początki mojego mierzenia się z techniką raycastingu. Drugi dzień zabawy tą techniką przyniósł kolejną aktualizację w postaci obsługi tekstur oraz kolizji. Ale po kolei.
System kolizji w zasadzie nie jest niczym skomplikowanym. Pierwsze podejście ograniczyłem tylko do sprawdzania, czy ruch w danym cyklu nie kończył się na polu oznaczonym jako ściana. Jeśli tak było, współrzędne były cofane, czyli ruch się nie wykonał. Problem, który ten sposób stwarzał, to brak możliwości „przytulania się” do ścian podczas zwiedzania poziomu (w połączeniu ze spacją dosyć standardowy sposób szukania ukrytych miejsc w grach Wolfenstein3D, czy Doom). Aby tego uniknąć dodatkowo w sytuacji, gdy postać zbliży się do krawędzi pola na którym się znajduje na mniej niż określona w kodzie wartość, sprawdzam, czy sąsiednie pole to ściana. Jeśli tak odsuwam postać od tej krawędzi na właśnie tą zdefiniowana odległość. Obsługiwane w ten sposób są niezależnie krawędzie góra-dół (współrzędna y), oraz lewo-prawo (współrzędna x), dzięki czemu błąd zostaje wyeliminowany.
Sposób na wyświetlanie tekstur, zamiast jednokolorowych ścian także jest w tej technice bardzo prosty i większość niezbędnych do tego danych już w poprzedniej wersji była uzyskana. Podczas obliczania odległości do ściany dla każdego z promieni jest uzyskiwana informacja, na jakich współrzędnych nastąpiło trafienie ze ścianą. Jest to zawsze liczba z zakresu [ 0, 1 ). W połączeniu z informacją o szerokości wyświetlanej na danej ścianie tekstury już niedaleka droga do obliczenia, którą kolumnę pikseli należy na danym promieniu wyświetlić. Wystarczy obie wartości pomnożyć przez siebie i rzutować do int.
Po pierwszym wyświetleniu tekstur szybko stał się zauważalny jeden błąd, którego występowanie podejrzewałem już wcześniej, ale było trudno o jego potwierdzenie.


Jak widać na powyższych obrazkach, tekstura wyświetlana w centrum obrazu jest szersza, niż na obrzeżach. Oznacza to, że równomierne rozmieszczenie promieni raycastingu na całym polu widzenia się nie sprawdza i trzeba to nieco zmienić. Poprawka sprowadza się do uwzględnienia dodatkowej wagi, której wartość jest zależna od tego, jak duży jest kąt między aktualnie liczonym promieniem, a kierunkiem patrzenia postaci. Dzięki temu możliwe jest zwiększenie gęstości promieni w centrum ekranu kosztem tych po bokach.
Po dodaniu tekstur z gry efekt już całkiem zbliżony do oryginału :)



Podjąłem także krótką próbę wyświetlania tekstury podłogi. Jednak zdecydowałem się z tym wstrzymać i odłożyć tę kwestię do kolejnej generacji silnika bazującej na Doom. W uzyskanym przeze mnie algorytmie wciąż były błędy, gdyż podłoga nie była rysowana prawidłowo, jednak głównym powodem zrezygnowania z dalszych prób naprawienia tego była kwestia wydajności. Moje podejście najwyraźniej nie było zbyt optymalne, gdyż FPS spadał dość drastycznie. W związku z tym nie było sensu dalszego poprawiania algorytmu w celu uzyskania prawidłowej perspektywy, gdyż i tak nie byłby on dołączony do kodu ze względu na wydajność.

Zgodnie z planami z poprzedniej notki zostało już tylko opakować uzyskany kod w prosty gameplay z możliwością tworzenia własnych poziomów. Ciąg dalszy nastąpi ;)
Linki:
Brak komentarzy