Skocz do zawartości

Super Simple Laser


Rekomendowane odpowiedzi

Download

v1.1

v1.11

Przykład sprawdzania kolizji

Przykład/engine lasera, z prostym patentem optymalizującym.

Jak to działa?

Najprostsza możliwa wersja takiego laserka działa tak, że pętla przesuwa się po lengthdirach o podaną liczbę pikseli, a kiedy natrafi na przeszkodę, jej działanie się przerywa i punkt, w którym stanęła, jest punktem "końcowym" lasera.

Niestety, to rozwiązanie jest dość niewydajne - jeśli funkcja będzie leciała po pikselu, to, jeśli przeszkoda będzie oddalona o powiedzmy 950px, to pętla będzie musiała wykonać się 950 razy, i m. in. sprawdzić kolizję 950 razy, co chyba nam się ie uśmiecha :P

 

laser(x, y, dir, prec1, prec2, maxr, obj);

x - startowa pozycja x

y - startowa pozycja y

dir - kąt, w którym ma lecieć laser/pocisk

prec1 - Precyzja pierwszego przebiegu lasera, im mniejsza, tym skrypt będzie działał szybciej (szczególnie na duże dystanse), im większa, tym większe przeszkody pocisk będzie mógł "przeskoczyć". Zalecana wartość ok. 15-25, zależnie od tego, jak duże przeszkody mamy w grze :P

prec2 - Właściwa precyzja lasera, z jaką dokładnością zostanie on "zatrzymany" na ścianie. Zalecana wartość - 1-5, zqleżnie od tego, jak dużą wartość prec1 ustawiłeś, i na jakiej precyzji Ci zależy :P

maxr - Maksymalny dystans, jaki może przejść laser/pocisk. Jeśli pocisk przeleci przez taki dystans, a nie napotka żadnej przeszkody - zatrzyma się w miejscu, a funkcja zwróci wartość 0. (nie testowałem, ale powinno działać :P )

obj - obiekt, do którego ma być sprawdzana kolizja

 

Tutaj nasza pętla najpierw "skacze" po 15px (czy jaką wartość sobie ustawimy (prec1)), a kiedy natknie na przeszkodę - cofa się co piksel (prec2) aż do momentu, kiedy pod nią NIE będzie przeszkody - wtedy zwraca nam swoją pozycję.

 

W moim przykładzie są 2 funkcje - laser(x, y, dir, prec1, prec2, maxr, obj), oraz laser_adv(x, y, dir, prec1, maxr, obj).

 

Teraz prosty przykład, czym różni się owy laser_adv() od laser().

"Zwykły" laser sprawdza kolizję poprzez funkcję collision_point(), w przeciwieństwie do laser_dv, który do tego celu używa collision_line() - z tego powodu prostsza wersja lasera jest nieznacznie wydajniejsza.

 

Jednakże należy wiedzieć, iż jeśli pierwszy, szybki przebieg pętli będzie liczony punktami - możemy po prostu przeskoczyć jakiś obiekt.

Jeśli prec1 będzie ustawione na 15, przy pechowym ustawieniu nasz laser będzie mógł przelecieć przez nawet 14-pikselową przeszkodę.

Najczęściej będzie się to ujawniało w postaci ucinania rogów:

54352628.png

 

Po to powstała funkcja laser_adv().

Ona, dzięki użyciu collision_line() zapobiega przenikaniu lasera przez jakiekolwiek przeszkody - chociażby bloczek miał 1px szerokości, a nasza funkcja jako prec1 miała ustawioną ekstremalną wartość - powiedzmy 50 (aczkolwiek nie polecam stosowania takich wysokich wartości - może i dzięki temu funkcja zyska parę kroków pętli w pierwszym przebiegu, ale za to może stracić duuużo więcej w ostatnim, precyzyjnym przebiegu).

33258074.png

 

Teraz coś o użyciu funkcji.

Powiedzmy, że chcemy zrobić sobie taki "lepsiejszy" system strzelania do tdsa. Mówiąc lepsiejszy mam na myśli to, żeby nie było tego, co jes dobijające w chyba wszystkich gmowych tdsach - że pociski lecą z określoną prędkością... :/ Zanim pocisk przeciwnika do mnie doleci, to ja spokojnie zrobię unik. WAT. We wszystckich fpsach jest tak, iż pocisk trafia w przeciwnika/ścianę dokładnie w tym fpsie, w którym strzeliliśmy. I jak dla mnie w tdsach powinno być tak samo :P

GMLif(mouse_check_button_pressed(mb_left))

{

laser(x, y, point_direction(x, y, mouse_x, mouse_y)-3+random(6), 15, 1, 2000, obj_contact));

//Tutaj albo zrób sobie obiekt o nazwie powiedzmy "obj_contact" i ustaw go jako parenta wszystkim obiektom, w które powinno się dać trafić pociskiem,

//albo daj ten kod w obj_bullet, któremu ustawisz sprite 1x1px, i będziesz mógł używać w funkcji place_free() (aczkolwiek zalecam pierwszą opcję)

 

instance_create(laser_x, laser_y, obj_bullet); //Tworzę pocisk tam, gdzie on się zatrzymał (funkcja laser() zwraca wynikowe pozycje do zmiennych laser_x i laser_y)

//teraz możesz normalnie dać event collision pocisku z przeciwnikiem/ścianą/czy czym tam chcesz.

//A, i dodaj do pocisku alarma, aby po 1 Stepie się zniszczył ;)

}

 

No, to będzie na tyle.

Nudzi mi się, to się nieźle rozpisałem :D

 

Edit: Poprawiłem jednego mini-buga (przy wartości prec2 większej niż 1 laser/pocisk nie zatrzymywał się na przeszkodzie, a minimalnie przed nią)

Edit2: Dodałem przykład sprawdzania kolizji :P

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ę...