Muchaszewski Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 Witam. Robię grę TPS (na razie w 2D). Mam problem. Chciałem zrobić w mojej grze strzelanie laserem. Nie było by problemu gdyby nie to że nie znam wystarczająco zoptymalizowanego kodu(zwłaszcza na dużych planszach). Chciałem napisać funkcję która sprawdzała by odległość od gracza do przeszkody po linii prostej, i zwracała by odległość, albo miejsce x,y do tej że przeszkody, a także kąt pod jakim jest gracz względem tej że przeszkody. Mój kod opiera się na szukaniu przeszkody przez funkcję collision_check_point kolejnego piksela do gracza w kierunku, w którym jest obrócony. Następnie sprawdza tą że pozycje pod kątem znajdującej się instancji i zwraca jej obrót. Wszystko ładnie, ale jeśli odległość od przeszkody jest większa niż 100 kratek to zaczyna się problem, a mam w planach aby laser ten odbijał się od pewnego rodzaju bloków i ponownie leciał dalej. Proszę o napisanie mi wystarczająco zoptymalizowanego kodu, abym nie musiał czekać paru sekund na strzał. Jakoś przeżyję zmniejszenie FPS! Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Konrad-GM Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 Platyna napisał artykuł o wyszukiwaniu binarnym, szybki i efektowny sposób ;) https://gmclan.org/index.php?artykul=74 Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
kt1117 Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 Trochę trudniej będzie jeśli chodzi o kąt. Ale możesz sprawdzać odległość dwóch linii między bohaterem a przeszkodą. Linie te tworzyły by kąt powiedzmy 5 stopni. Wtedy dostajesz na boki trójkąta i za pomocą sinusów kosinusów itd. obliczasz trzeci. Dzięki temu dostaniesz trójkąt w którym będziesz musiał wyznaczyć kąty między resztą boków. Wybierzesz sobie jeden z nich (wyjdzie w praniu który) i masz problem rozwiązany. Kodu Ci nie napiszę, bo nie pamiętam wzorów na te wszystkie kąty. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rudy Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 Albo po prostu opisać każdą przeszkodę punktami krańcowymi i przy kolizji odwoływać się do nich. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Muchaszewski Opublikowano 19 Sierpnia 2011 Autor Udostępnij Opublikowano 19 Sierpnia 2011 Platyna napisał artykuł o wyszukiwaniu binarnym, szybki i efektowny sposób ;) https://gmclan.org/index.php?artykul=74 Dzięki ;P Będąc na "przechadzce" wpadłem na bardzo podobny pomysł xD Mój "pomysł" będzie szukał najpierw przeszkody co 100 kratek jeśli nie znajdzie przeszuka w kolejnych 100 kratkach, a następnie będzie dzielił to 100 na mniejsze części. Wydaje mi się to bardziej zoptymalizowane biorąc pod uwagę krótkie odległości, gdyż w wyszukiwaniu binarnym Platyna sugeruje podanie od razu maksymalnej odległości strzału. Trochę trudniej będzie jeśli chodzi o kąt. (...) Wtedy dostajesz na boki trójkąta i za pomocą sinusów kosinusów itd. obliczasz trzeci. (...) Jest to dobry pomysł, ale trudny do realizacji. Z matmy jestem prawdopodobnie "dobry" :P Ale nie wyobrażam sobie jak by można poprowadzić te 2 linie od gracza i przeszkody. A tak w sumie poco sobie utrudniać. Albo po prostu opisać każdą przeszkodę punktami krańcowymi i przy kolizji odwoływać się do nich. To też nie ma sensu. Prościej jest stworzyć jak najbardziej standardowe przeszkody, do których się wpisze kierunek, a następnie do tego kierunku się odwołać :P Problemem przy moim pomyśle i kt1117 są wszelkiego rodzaju kule, i obszary koliste, ponieważ ciężko będzie określić dokładnie w jakim kierunku mój laser miał by się "odbić". Ale i tak dzięki. Mam jeszcze jedno pytanie co do tego. Znalazłem dokładne położenie przeszkody, ale mam problem. Teraz po prostu nie wiem jak można było by się do niej odwołać. Korzystam z instance_nearest(...) ale nie jest to najlepszy pomysł, zwłaszcza przy ciasno upakowanych obiektach. Czy jest jakaś funkcja (jest na pewno, ale zapomniałem jaka ;p) która pozwoli mi się odwołać do obiektu w danym miejscu. Wystarczy id obiektu xD Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Sernat Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 To też nie ma sensu. Prościej jest stworzyć jak najbardziej standardowe przeszkody, do których się wpisze kierunek, a następnie do tego kierunku się odwołać :P Problemem przy moim pomyśle i kt1117 są wszelkiego rodzaju kule, i obszary koliste, ponieważ ciężko będzie określić dokładnie w jakim kierunku mój laser miał by się "odbić". Ale i tak dzięki. Jak to jak mają się odbić? Zgodnie z prawami fizyki! A te są jednoznaczne. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
CuB3 Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 Widzę, że do szkoły się nie chodzi, albo wagaruje na lekcjach fizyki :P http://pl.wikipedia.org/wiki/Odbicie_fali Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rudy Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 Dzięki ;P Będąc na "przechadzce" wpadłem na bardzo podobny pomysł xD Mój "pomysł" będzie szukał najpierw przeszkody co 100 kratek jeśli nie znajdzie przeszuka w kolejnych 100 kratkach, a następnie będzie dzielił to 100 na mniejsze części. Wydaje mi się to bardziej zoptymalizowane biorąc pod uwagę krótkie odległości, gdyż w wyszukiwaniu binarnym Platyna sugeruje podanie od razu maksymalnej odległości strzału. Jest to optymalizacja ale mała. Sposób? Ustaw maksymalny test na cały room. Wtedy dalszego zasięgu nie będzie, a sprawdzanie binarne jest chyba najbardziej zoptymalizowanym sposobem. A jeśli już chcesz swój pomysł, to nie dziel na 100 mniejszych tylko binarnie (wtedy zamiast 100 masz 7 sprawdzeń ;P ). Prościej jest stworzyć jak najbardziej standardowe przeszkody, do których się wpisze kierunek, a następnie do tego kierunku się odwołać :P Im więcej obiektów tym więcej ma GM do przetworzenia, a jeśli będziesz miał takie rozwiązanie, będzie mniej obliczeń bez efektu (jak kontrola zmiennych prędkości, animacji itd, każdy obiekt to ma) Problemem przy moim pomyśle i kt1117 są wszelkiego rodzaju kule, i obszary koliste, ponieważ ciężko będzie określić dokładnie w jakim kierunku mój laser miał by się "odbić". Ale i tak dzięki. No właśnie, a tak jeżeli płaska powierzchnia - wpisujesz do danych dwa punkty i przy odbiciu odwołujesz się do nich. Mam jeszcze jedno pytanie co do tego. Znalazłem dokładne położenie przeszkody, ale mam problem. Teraz po prostu nie wiem jak można było by się do niej odwołać. Korzystam z instance_nearest(...) ale nie jest to najlepszy pomysł, zwłaszcza przy ciasno upakowanych obiektach. Czy jest jakaś funkcja (jest na pewno, ale zapomniałem jaka ;p) która pozwoli mi się odwołać do obiektu w danym miejscu. Wystarczy id obiektu xD collision_point powinno załatwić sprawę ;) . Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Muchaszewski Opublikowano 19 Sierpnia 2011 Autor Udostępnij Opublikowano 19 Sierpnia 2011 (edytowane) To akurat wiedziałem że kąt odbicia zależy od kąta padania i tu raczej nie mam problemu... (dobra z fizyki jestem cienki ;p) Właśnie myśląc nad tym zdałem sobie sprawę że be funkcji trygonometrycznych się to nie obejdzie a kt1117 źle zrozumiałem :P Ale ciężko mi wymyślić jakieś rozwiązanie. Myślę nad tym aby kąt zewnętrzny pomiędzy przeszkodą, a laserem podzielić na 2, a wynik będzie kątem odbicia względem przeszkody, ale coś mi się wydaje że źle myślę. )Jeszcze zanim to napisałem znalazłem błąd :P jeśli kąt pomiędzy przeszkodą a laserem wynosie 90 stopni z każdej strony?) Jak czasami widzę te wszystkie wzory na Wikipedii to mnie krew zalewa, więc prosiłbym o jakąś uproszczoną wersję, bądź realny pomysł. EDIT: collision_point powinno załatwić sprawę Ta funkcja zwraca tylko 2 wartości true i false. Więc niestety nie Jest to optymalizacja ale mała. Sposób? Ustaw maksymalny test na cały room. Wtedy dalszego zasięgu nie będzie, a sprawdzanie binarne jest chyba najbardziej zoptymalizowanym sposobem. A jeśli już chcesz swój pomysł, to nie dziel na 100 mniejszych tylko binarnie (wtedy zamiast 100 masz 7 sprawdzeń ;P ). Właśnie o to mi chodziło, ale zapomniałem dodać :P Edytowane 19 Sierpnia 2011 przez Muchaszewski Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
CuB3 Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 Jak kąt wejściowy i wypadowy może mieć po 90 stopni? :o Większej głupoty w życiu nie słyszałem... Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Muchaszewski Opublikowano 19 Sierpnia 2011 Autor Udostępnij Opublikowano 19 Sierpnia 2011 Hmm źle się zrozumieliśmy, albo źle napisałem ;p Jeśli strzelimy do płaskiej ściany laserem pod kątem 90 stopni to co się stanie?? Wróci tą samą drogą więc będzie mieć również 90 stopni (Kąt ten jest oczywiście względem ściany). Chyba że... a zresztą. Ja się nie znam. A co do wszystkich funkcji collision coś mi nie działało więc chciałem zobaczyć co zwraca ta funkcja :P Wszystkie te funkcje zwracają id obiektu który stoi im na drodze jako pierwszy :P To rozwiązuje wszystkie moje problemy, ale i tak skorzystam z wyliczania dokładnej pozycji "namierzania" :P Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Konrad-GM Opublikowano 19 Sierpnia 2011 Udostępnij Opublikowano 19 Sierpnia 2011 Dzięki ;P Będąc na "przechadzce" wpadłem na bardzo podobny pomysł xD Mój "pomysł" będzie szukał najpierw przeszkody co 100 kratek jeśli nie znajdzie przeszuka w kolejnych 100 kratkach, a następnie będzie dzielił to 100 na mniejsze części. Wydaje mi się to bardziej zoptymalizowane biorąc pod uwagę krótkie odległości, gdyż w wyszukiwaniu binarnym Platyna sugeruje podanie od razu maksymalnej odległości strzału. Wyszukiwanie binarne + collision_line w tym przypadku będzie szybsze ;) Mam jeszcze jedno pytanie co do tego. Znalazłem dokładne położenie przeszkody, ale mam problem. Teraz po prostu nie wiem jak można było by się do niej odwołać. Korzystam z instance_nearest(...) ale nie jest to najlepszy pomysł, zwłaszcza przy ciasno upakowanych obiektach. Czy jest jakaś funkcja (jest na pewno, ale zapomniałem jaka ;p) która pozwoli mi się odwołać do obiektu w danym miejscu. Wystarczy id obiektu xD instance_position(...); Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Muuuuczek567 Opublikowano 20 Sierpnia 2011 Udostępnij Opublikowano 20 Sierpnia 2011 collision_point powinno załatwić sprawę Ta funkcja zwraca tylko 2 wartości true i false. Więc niestety nie Mylisz się. Wszystkie funkcje collision_ zwracają ID obiektu, jeśli jest jakiś obiekt w polu oznaczonym argumentami funkcji, w przeciwnym wypadku zwracają noone (-4, czyli w sumie false). collision_point zadziała. Wyszukiwanie binarne + collision_line jest bardzo dobrym pomysłem, gdyż zwiększenie zasięgu dwukrotnie spowoduje wydłużenie czasu obliczeń tylko o jedno wywołanie. Nie stracisz fps. Gdzieś nawet zamieściłem kompletny skrypt, możesz poszukać w dziale "Skrypty, przykłady, dodatki" albo przeszukać moje tematy. Obliczanie kątu jest bardzo proste. Musisz tylko wiedzieć, do czego służy point_direction(x1,y1,x2,y2) i wykorzystać to. Ta funkcja pozwoli Ci również obliczyć kąt odbicia promienia od powierzchni kulistych. Mam nadzieję, że pomogłem :-) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Muchaszewski Opublikowano 20 Sierpnia 2011 Autor Udostępnij Opublikowano 20 Sierpnia 2011 Ta funkcja zwraca tylko 2 wartości true i false. Więc niestety nie Mylisz się. Wszystkie funkcje collision_ zwracają ID obiektu, jeśli jest jakiś obiekt w polu oznaczonym argumentami funkcji, w przeciwnym wypadku zwracają noone (-4, czyli w sumie false). collision_point zadziała. A co do wszystkich funkcji collision coś mi nie działało więc chciałem zobaczyć co zwraca ta funkcja :P Wszystkie te funkcje zwracają id obiektu który stoi im na drodze jako pierwszy :P Obliczanie kątu jest bardzo proste. Musisz tylko wiedzieć, do czego służy point_direction(x1,y1,x2,y2) i wykorzystać to. Ta funkcja pozwoli Ci również obliczyć kąt odbicia promienia od powierzchni kulistych. Nie wiem jak point direction miał by mi pomóc. Zastanawiam się już od dłuższej chwili nad tym i nic nie przychodzi mi do głowy. Point_direction zwraca kierunek pomiędzy 2 punktami ale jakie te punkty bym miał użyć?? Wyszukiwanie binarne + collision_line jest bardzo dobrym pomysłem, gdyż zwiększenie zasięgu dwukrotnie spowoduje wydłużenie czasu obliczeń tylko o jedno wywołanie. Nie stracisz fps. Gdzieś nawet zamieściłem kompletny skrypt, możesz poszukać w dziale "Skrypty, przykłady, dodatki" albo przeszukać moje tematy.Nie mogę znaleźć tego przykładu, ale wydaje mi się że mam już coś wystarczająco zoptymalizowanego. Zjada tylko 50fps przy 400 początkowych więc rezultat jest zadowalający przy mapce 10000x10000 :P Ale skrypt i tak się przyda. EDIT: Drobne sprostowanie co do wydajności. Coś zrobiłem i wydajność mi spadła masakryczne. 5fps jeśli obiekt jest blisko a 40 jeśli jest daleko. :( Muszę napisać wszystko od początku, bo backupa nie mam. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
ediepl Opublikowano 20 Sierpnia 2011 Udostępnij Opublikowano 20 Sierpnia 2011 Wykombinowałem coś takiego https://gmclan.org/up7191_12_collision.html sprawdza kolizje na mapie 10000x10000 prawie bez utraty fps. EDIT:Poprawione. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Muuuuczek567 Opublikowano 20 Sierpnia 2011 Udostępnij Opublikowano 20 Sierpnia 2011 Kąt pod jakim gracz jest względem przeszkody: GML a = direction-point_direction(x,y,przeszkoda.x,przeszkoda.y) if(a < 0) a += 360 Mogłem coś źle zrozumieć, ale tak to generalnie wygląda. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Sernat Opublikowano 20 Sierpnia 2011 Udostępnij Opublikowano 20 Sierpnia 2011 GML a = direction-point_direction(x,y,przeszkoda.x,przeszkoda.y) while(a < 0) a += 360 Jeśli już. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Muuuuczek567 Opublikowano 20 Sierpnia 2011 Udostępnij Opublikowano 20 Sierpnia 2011 Zmienna a nigdy nie będzie mniejsza od liczby -360, więc pętla jest niepotrzebna. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rudy Opublikowano 20 Sierpnia 2011 Udostępnij Opublikowano 20 Sierpnia 2011 Zrobiłem mały przykładzik co do moich rozważań odbicia lasera. Sprawdź, czy ci pasuje. Każda odbicie zwalnia pfs o mniej więcej 30 z 600, przy roomie 10000x10000 (na mniejszym różnica 2-4 fps). Rzuć okiem, czy ci odpowiada. Jedynie co to musisz opisać za pomocą prostych i krzywych swoje figury. Ewentualnie ulepszysz kod o kolejne typy powierzchni :) . PLIK Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
ediepl Opublikowano 20 Sierpnia 2011 Udostępnij Opublikowano 20 Sierpnia 2011 Muszę przyznać że niezłe, ale strasznie dużo kodu, zaraz spróbuje zrobić coś prostszego. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
kt1117 Opublikowano 21 Sierpnia 2011 Udostępnij Opublikowano 21 Sierpnia 2011 Najlepiej by było napisać funkcję, zwracającą najmniejszy kąt, pomiędzy 2 liniami. Spróbuję coś wymyślić, bo wydaje mi się, że tak będzie najłatwiej. E:Sprawdźcie czy dobrze działa: GML ax1=argument0 ay1=argument1 ax2=argument2 ay2=argument3 bx1=argument4 by1=argument5 bx2=argument6 by2=argument7 kba=point_direction(ax1,ay1,ax2,ay2) kbb=point_direction(bx1,by1,bx2,by2) return abs(kba-kbb) E2:Teraz łatwo wprowadzić w życie mój pomysł: 1.Za pomocą kombinacji lenghdir'ów collision_line i wyszukiwania binarnego wyznaczasz współrzędne dwóch liń, które idą 1* w lewo i w prawo od kierunku bohatera, aż do napotkania przeszkody. 2.Między końcami tych liń od strony przeszkody wyznaczasz trzecią linię. 3.Za pomocą mojej funkcji wyliczasz kąt między linią strzału lasera a przeszkodą. 4.Dostajesz kąt odbicia, wykonujesz na nim działanie: GML kat=kat+(180-(kat*2)) E3:Na kulach najlepiej działa z bliska, na płaskich powinno nie mieć to wpływu. Chodzi o to, że kąt rozszerza się, tzn. im dalej od wierzchołka mierzysz odległość między ramionami, tym ta odległość jest większa. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rudy Opublikowano 21 Sierpnia 2011 Udostępnij Opublikowano 21 Sierpnia 2011 Ten skrypt mam też w przykładzie, dircmp, jedynie bez wyznaczania kierunku przez point_direction, ale za to zwracający różnicę zawsze w zakresie (-180, 180>. Można i tak, lecz co jeśli będzie bardzo mała przeszkoda w bardzo dużej odległości? Albo jeśli będzie odbijało się tuż przy wieszchołku? Wtedy jedna/dwie linie będą miały końce zupełnie gdzie indziej i efekt wyjdzie... nie taki jak powinien być ;P Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
kt1117 Opublikowano 22 Sierpnia 2011 Udostępnij Opublikowano 22 Sierpnia 2011 Właśnie o tym mówiłem, ale w większości gier obiekty są ustawione bardziej bliżej siebie, a ten kod nie powinien zabrać zbyt dużo FPS. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rekomendowane odpowiedzi
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ę