Skocz do zawartości

Instance_nearest dzialajaca w danym zakresie wspolrzednych


TO_mek

Rekomendowane odpowiedzi

Witam!

Jak dokładnie działa instance_nearest? Wybiera najbliższy obiekt po okręgu (najkrótszy promień)? Jest dostępna jakaś lista znalezionych obiektów posortowana wg odległości?

 

Potrzebuje znajdować najbliższy obiekt ale na dużym roomie w zakresie całej szerokości ale w ograniczonym zakresie wysokości czyli w prostokącie o zadanej wysokości.

Może coś na zasadzie znajdowania najbliższego obiektu a później sprawdzania czy ten obiekt ma y w odpowiednim zakresie (tyle sam potrafię) ale w momencie kiedy jednak ten najbliższy obiekt jest poza szukanym zakresem (za duży lub za mały X) jak wyszukać "drugi w kolejności najbliższy obiekt"?

Odnośnik do komentarza
Udostępnij na innych stronach

Najłatwiej przejrzeć wszystkie obiekty. Dla każdego sprawdzić czy się znajduje w zadanym obszarze, a jeśli tak to czy jest bliżej od aktualnie najbliższego. W takim przypadku zapomnieć o poprzednim i zapamiętać jego.

 

GML
var xxx;

var yyy;

var dist;

var obj;

dist = 1000000000; //Tu będziemy przechowywać dystans to aktualnie najbliższego znalezionego. Na początku jakaś wielka wartość.

obj = 0; //Tu będziemy przechowywać id tego najbliższego

xxx=x;

yyy=y; //zapamiętujemy w globalnych tymczasowych współrzędne od których odległość chcemy mierzyć

with(nazwa_obiektu) //przeglądamy wszystkie obiekty nazwa_obiektu w pętli

{

if(x>granica_lewa && x<granica_prawa && y>granica_gorna && y<granica_dolna) //jeśli nasz obiekt jest w zadanym obszarze...

{

if(point_distance(xxx,yyy,x,y)<dist) //jeśli nasz obiekt jest bliżej od aktualnie znalezionego

{

dist = point_distance(xxx,yyy,x,y); //zapamiętujemy nową, mniejszą odległość

obj=id; //oraz zapamiętujemy id znalezionego obiektu

}

}

}

 

Na końcu skryptu w zmiennej obj masz id znalezionego obiektu. Tylko pamiętaj, że obj jest zmienną tymczasową. Po zakończeniu skryptu zniknie więc przepisz wartość do innej zwykłej zmiennej.

Odnośnik do komentarza
Udostępnij na innych stronach

No to inaczej. Czy takie sprawdzanie nie będzie wolniejsze niż sytuacja jaką mam teraz czyli:

- jeden obiekt "hero"

- dużo obiektów "przeciwnik" (na razie 10 ale docelowo pewnie 100 albo więcej)

 

Obecnie sprawdzam w każdym obiekcie "przeciwnik" odległość od "hero":

 

if (point_distance(x,y,hero_obj.x,hero_obj.y) < gonic) and (abs(y-hero_obj.y) < 30) then {

przeciwnik_atakuje_hero();

}

 

gdzie:

gonic - to odległość na jaką reaguje przeciwnik

(abs(y-hero_obj.y) < 30) - zakres pionowy czyli interesuje mnie tylko pasek ekranu o wysokości +/- 30px

przeciwnik_atakuje_hero() - skrypt który powoduje atak na hero (przyspieszenie przeciwnika w kierunku hero)

 

Czyli za każdym razem w stepie każdego przeciwnika wykonuje się zbędny kod a ja chciałem uzyskać by podobny kod był wykonywany tylko w step jednego obiektu hero bo i tak atakować powinien tylko najbliższy przeciwnik ale nie w okręgu tylko w pasie ekranu o wysokości +/- 30px (a szerokości maksymalnej rooma). Jedyny problem to znalezienie tego najbliższego przeciwnika w danym zakresie (bo często będzie sytuacja gdzie będą przeciwnicy dużo bliżej ale na wyższym/niższym piętrze niż znajduje się hero i oni nie mogą atakować przez sufit/podłogę).

Odnośnik do komentarza
Udostępnij na innych stronach

Kod, który Ci dałem jest w porządku. Myślę, że jak go dasz w stepie to nie będzie to bardzo powolne. Musiałbyś mieć bardzo dużo tych przeciwników. Jak nie ma ich więcej niż, powiedzmy, sto to śmiało możesz użyć tego kodu. Oczywiści dałoby się zrobić to szybciej używając bardziej skomplikowanych algorytmów, ale myślę, że nie ma co się bawić w takie rzeczy. Mój kod działa liniowo do ilości przeciwników. To całkiem nieźle.

 

Jakiś taki pierwszy pomysł, który mi się nasuwa by zrobić to szybciej to dla każdego piętra trzymać posortowaną po współrzędnych x tablicę przeciwników i później algorytmem wyszukiwania binarnego sprawdzić między, którymi 2 przeciwnikami jest hero i wybrać bliższego z nich. Jednak to by się sprawdzało tylko w przypadku gdy porządek w tej tablicy się nie zmienia czyli przeciwnicy nie mogą się wyminąć.

 

Ale naprawdę uważam, że kod jaki podałem jest wystarczający. To nic strasznego jeśli dla każdego przeciwnika zrobi się taką drobnostkę w każdym step. Ewentualnie można go lekko przyspieszyć, np nie wywołując nie potrzebnie 2 razy funkcji point_distance().

GML
var xxx;

var yyy;

var dist;

var obj;

dist = 1000000000; //Tu będziemy przechowywać dystans to aktualnie najbliższego znalezionego. Na początku jakaś wielka wartość.

obj = 0; //Tu będziemy przechowywać id tego najbliższego

xxx=x;

yyy=y; //zapamiętujemy w globalnych tymczasowych współrzędne od których odległość chcemy mierzyć

with(nazwa_obiektu) //przeglądamy wszystkie obiekty nazwa_obiektu w pętli

{

if(abs(y-yyy) < 30) //jeśli nasz obiekt jest w zadanym obszarze...

{

d=point_distance(xxx,yyy,x,y)

if(d<dist) //jeśli nasz obiekt jest bliżej od aktualnie znalezionego

{

dist = d; //zapamiętujemy nową, mniejszą odległość

obj=id; //oraz zapamiętujemy id znalezionego obiektu

}

}

}

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