Skocz do zawartości

Strzały po krzywej linii


SimianVirus7

Rekomendowane odpowiedzi

Siemanko^^

Jako, że jestem burak z matmy, potrzebuję pomocy. Chcę zrobić aby wróg atakował gracza magicznym kółkiem (super zaklęcie). Ale nie chcę tego robić w prosty sposób, jak:
 

speed = 8;
direction = point_direction(x, y, oPlayer.x, oPlayer.y);

Graficznie:

https://imgur.com/a/1qfdfk3


Mam na myśli, żeby zrobić to po linii pochyłej:
https://imgur.com/lqZjX3M

Próbowałem coś z sinusami, ale marny wynik (przypominam o beztalenciu do matematyki). Później coś zaświtało i całkiem przyjemny efekt wyszedł za pomocną ścieżek:
 

///rysuj sciezke
var _pd = point_distance(x,y, oPlayer.x, oPlayer.y);

bullet_path = path_add();

path_add_point(bullet_path, x, y, 100); //start
path_add_point(bullet_path, x+ _pd/2, y+50, 100); //srodek
path_add_point(bullet_path, oPlayer.x, oPlayer.y, 100); //koniec



path_set_kind(bullet_path, true);
path_set_precision(bullet_path, 8);
path_set_closed(bullet_path, false);

path_start(bullet_path, speed, path_action_stop, 0);

i wyglądało to, jak na gifie powyżej, aczkolwiek tylko i wyłącznie wtedy, kiedy byłem z wrogiem w tej samej linii, czyli nasze y było takie samo, bądź zbliżone. Pobawiłem się chwilę z path_rotate ale nic z tego.
Jakieś malutkie nakierowanie, jakby to zrobić?

 

PS: przy okazji możecie mi powiedzieć jak osadzać gify, żeby nie było hiperłączy :P

Odnośnik do komentarza
Udostępnij na innych stronach

Cześć, przy użyciu sinusa i lengthdirów można spokojnie taki efekt uzyskać. Zrobiłem mały przykład, jak można to ugryźć z sinusem.

Spellcaster.gmz

 

Generalnie, to na początek tworzymy dwie zmienne wirtualnej pozycji pocisku na scenie ghost_x=x i ghost_y=y, liczymy startową odległość między początkową pozycją pocisku a jej celem i zapisujemy do zmiennej lokalnej start_distance. Następnie w step należy policzyć aktualną odległość między pociskiem a celem i na podstawie wyliczonej wartości stworzyć zmienną factor wykorzystując sinusa: var factor=sin((distance/start_distance) * pi) - ta zmienna ma wartość od 0 (pozycja startowa/końcowa) do 1 (w środku drogi) i będzie odpowiadać za łuk pocisku. Do wyliczenia łuku użyjemy lengthdirów: var offsetx=lengthdir_x(<maksymalne_wygiecie> * factor, <kierunek_pocisku> + 90), dla lengthdir_y funkcja wygląda tak samo. Na koniec ustawiamy pozycję x,y z przesunięciem: x=ghost_x+offsetx oraz y=ghost_y+offsety i gotowe.

 

Odnośnik do komentarza
Udostępnij na innych stronach

Eh, poddaje się ._.

Próbowałem to ogarnąć przez te 3 dni wraz z poradnikiem https://csanyk.com/2012/10/game-maker-wave-motion-tutorial/ ale no nie wychodzi mi to. Mógłbyś dać swój przykład na inny hosting, bo nie mam do niego dostępu :P Chcę jeszcze troszkę popróbować.
Dzięki za pomoc^^

Odnośnik do komentarza
Udostępnij na innych stronach

Dziękuje! Chodzi dokładnie tak, jak chciałem. Patrząc i analizując Twój kod, widziałem gdzie popełniałem błędy i nie rozumiem tylko tej linijki (prawdopodobnie dlatego, że występują tam dwie funkcje matematyczne ._.) 
 

// glowna funkcja przesuniecia
var factor = sin((distance / start_distance) * pi);		// i tu też do końca nie wiem, dlaczego mnożymy przez pi 
var maxlen = sqr(log2(start_distance));				// <---------------- TEJ

var offx = lengthdir_x(maxlen * factor, angle90);
var offy = lengthdir_y(maxlen * factor, angle90);


Wynik bardzo mnie zadowala, plus dodałem wybieranie czy pocisk ma lecieć z dołu czy z góry :> 
https://imgur.com/a/60zCDPN

Odnośnik do komentarza
Udostępnij na innych stronach

Super, że działa, a co do tych dwóch linijek kodu:

var factor = sin((distance / start_distance) * pi);

Jak podzielimy start_distance przez distance, otrzymamy wartości 0 - gdy czar jest najdalej od gracza i 1 - gdy pocisk jest najbliżej gracza, jest to funkcja liniowa i wygląda tak:


image.png.499cd0dc351e7d1c73090add5a1fc626.png

Jak widzisz, funkcja liniowa nie jest za ciekawa, ale przy użyciu sinusa, można uzyskać taki efekt:


image.png.376a084cdf06dbc13ca136a80f2df9d2.png
 

Funkcja sin jest funkcją trygonometryczną i przyjmuje wartość w radianach, powyższy wykres przedstawia wartości od 0 stopni do 360 stopni, odpowiednio w radianach będzie to 0 radianów i 2*PI radianów. Wartość tej poprzedniej liniowej funkcji (od 0 do 1) mnożymy przez wartość PI (180 stopni, od 0 do liczby PI), wstawiamy tę wartość do funkcji sin i otrzymujemy interesujący nas łuk:

 

image.png.f0f96dfcbf5f074f2171a5aa0af8899b.png

 

Funkcja sinusowa zwróci nam wartość od 0 do 1 - gdzie 0 jest na początku łuku, 1 jest środkiem i 0 również występuje na końcu łuku.

 

Jak widzisz, funkcję liniową zamieniliśmy na krzywiznę. Teraz przejdźmy do drugiej funkcji:

var maxlen = sqr(log2(start_distance));

Ta funkcja to nic innego jak logarytm naturalny do kwadratu. Generalnie to tę funkcję można zmieniać wedle uznania. Odpowiada ona za maksymalne wychylenie na naszym łuku. Jeżeli gracz będzie bliżej czarownika, to odchylenia będzie mniejsze, jak się gracz oddali od niego, to zwiększymy odpowiednio maksymalne odchylenie i pocisk będzie leciał po większym łuku. Funkcja logarytmiczna do kwadratu wygląda tak:


image.png.c0d5edb63707dc09eb589f8cc1036592.png

 

Możesz też np. użyć pierwiastka sqrt, której wykres funkcji wygląda tak:

 

image.png.8071aa49ca2d1d64a55fe1796797be0a.png


  

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