Skocz do zawartości

FOV, Linia wzroku


Rekomendowane odpowiedzi

Witam

 

Pisze grę (C#,XNA) strategiczną 2D , Widok z góry..

 

Jednostki gracza maja mieć zasięg wzroku (np kąt 90 stopni, długość 300 pikseli)

Na planszy znajdują się obiekty ( w formie prostokątów) których współrzędne mam zapisane. Te obiekty maja blokować fov'a.

 

Oto przykład

przyklad.jpg

 

Ma ktoś pomysł jak takie coś wykonać?

 

Myślałem aby poszczać linie o długości lini wzroku i sprawdzać jej kolizję z obszarami , następnie obrócić ją o kąt i tak długo aż pokryje całe pole fov'a. Tylko nie wiem czy to dobry pomysł.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
Poszukaj przykładu "Latarka.gmk" tu na gmclanie opartego na surfaces. Niestety nie pamiętam dokładnie gdzie to leży a autor nie raczył nic wpisać do game information.

napisał, że nie w gmie, a w c#

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
A rozumiesz, że sposób rozwiązania problemu można zaadoptować na potrzeby C#?

Musiałby mieć gma, żeby to odpalić mistrzuniu

Podejrzewam, że nikt nie będzie chciał płacić 20 dolców żeby zobaczyć przykładzik.

Odnośnik do komentarza
Udostępnij na innych stronach

Musiałby mieć gma, żeby to odpalić mistrzuniu

Podejrzewam, że nikt nie będzie chciał płacić 20 dolców żeby zobaczyć przykładzik.

 

Nie do końca się zgodzę :). Pomijając piracenie GMa, można przecież uruchomić wersję lite gdzie kod oraz help będzie dostępny a jeśli użyto w przykładach funkcji z GM Pro to zawsze ktoś na forum może przekompilować przykład do exe.

A link do artykułu o którym pisze Tymon to https://gmclan.org/index.php?czytajart=74

Odnośnik do komentarza
Udostępnij na innych stronach

Ja bym proponował takie coś (bardziej złożone ale jeśli Ci wyjdzie to będzie wydajniejsze i jednocześnie nie będzie używać niepotrzbnych render targetów.

A w ogóle to wykorzystanie przeszukiwania binarnego do zrobienia "lasera" ma sens tylko w gmie, gdzie wywołanie funkcji kilka razy więcej jest mniej optymalne niż sprawdzanie (przez grę już) dwa razy tyle pikseli ile rzeczywiście potrzeba <- taka uwaga do autora aby nie przyszło mu do głowy napisać własne collision_line i skopiować kod.

 

Więc tak:

1. Lecisz w pętli po wszystkich ściankach, interesują Cię tylko te, które są zwrócone do gracza _twarzą_ (możesz sprawdzać kąt, możesz porównywać pozycje, możesz pojechać iloczynem skalarnym (vector2.dot), jak Ci będzie bardziej pasować. jeśli to tylko prostokąty to porównywanie pozycji wystarczy). I teraz tak:

2. Jeśli oba wierzchołki ścianki są w zasięgu pova (vector2.distance()) (na rysunku jasny szary) to po prostu rysujesz trójkącik <player, punkt1, punkt2>, banał

3. Jeśli żaden z wierzchołków ścianki nie jest w zasięgu pova to nic nie rysujemy, też chyba banał

4. Jeśli tylko jeden wierzchołek jest w zasięgu pova (ciemny czary) robi się ciężej, tym razem punkt2 jest poza granicą widoczności więc jego wykorzystać jako wierzchołka nie możemy.

(przenosimy się na rysunek 2)

5. Na pewno musimy narysować trójkąt <player, punkt1(ten po lewej), miejsce przecięcia naszej ścianki z granicą fova (na rysunku zielona kropeczka)>.

Nie bardzo chce mi się teraz myśleć jak to liczyć, ale jakoś znajdziesz na necie "line circle intersection".

Trójkącik na rysunku (drugim rysunku ofc) jest zakolorowany na ciemnoszaro).

6. Na koniec zostaje _tylko_ wypełnić pozostałe białe miejsca (te, któe były białe od początku jak i te, które pozostawiliśmy czyste w punkcie 4/5) fovem, z dokładnością np. do 5 stopni - aby wyszło ładne "koło".

Konkretnie jak to zrobić też nie myślałem, ale na pewno będziesz musiał mieć jakąś _kolekcję_, która będzie Ci umownie symbolizować rozpiętość kątu 0 - 360 stopni (0 - 2pi, żeby nie konwertować niepotrzebnie tych kątów co chwila), tak, że będziesz mógł z niej dowolnie "wycinać" fragmenty - dla przykładu masz czystą kolekcję:

 

1. 0 - 360 //usuwamy fragment 100-200

2. 0-100, 200-360//usuwamy fragment 50-150

3. 0-50, 200-360

 

Itd. To co "usuwamy" to ofc wszystkie trójkąty, które narazie rysowaliśmy.

I teraz już naprawdę _tylko_ lecisz po tych segmentach, które zostały w tej kolekcji i je rysujesz, odpowiednio zwiększając liczbę trójkątów coby wyszło bardziej okrągłe (no wiesz, coś jakbyś rysował koło).

 

Gdybyś sobie z tym nie dał rady albo ta technika sama z siebie by nie działała (mogłem na coś nie wpaść, chociaż wydaje się dobrze) to zostaje sposób graficzny - robisz render targeta o rozmiarze jaki ten fov ma mieć, i najpierw na nim rysujesz (niech będzie na biało) całe koło, później "wycinasz" (niech będzie rysujesz na czarno) z niego obszary zasłonięte przez ścianki - coś, jakby te ścianki rzucały cienie. Wcześniej cieniowaliśmy wszystko PRZED ścianką (i trzeba było kombinować żeby nie wyjechać poza dystans fova) - teraz rysujemy wszystko ZA ścianką - i nie ma tu żadnego kombinowania, dla każdej ścianki która potencjalnie znajduje się w fovie "tak samo" rysujesz za nią dwa trójkąty.

Ten sposób jest dużo prostszy i pewniejszy, ale z wydajnością będzie troszkę gorzej - więc jeśli tych jednostek ma być dużo to zastanów się nad tą pierwszą techniką.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...