Skocz do zawartości

Liczenie obiektów w zasięgu


Draconis

Rekomendowane odpowiedzi

Witam.

Potrzebuję sposobu, na liczenie obiektów określonego typu w promieniu n.px od określonego obiektu, inaczej mówiąc, by dana akcja się wykonywała wtedy i tylko wtedy gdy w sąsiedztwie Obiektu_a znajdowała się określona liczba obiektów_b np. tylko dla 3 lub 4 a dla 1,2,5,>5 już nie, jako iż projekt jest w siatce, próbowałem użyć takiego kodu:

 

GML
s=0

if collision_point(x+5,y+5,object,1,0) then s=s+1

if collision_point(x+5,y,object,1,0) then s=s+1

if collision_point(x+5,y-5,object,1,0) then s=s+1

if collision_point(x-5,y+5,object,1,0) then s=s+1

if collision_point(x-5,y,object,1,0) then s=s+1

if collision_point(x-5,y-5,object,1,0) then s=s+1

if collision_point(x,y+5,object,1,0) then s=s+1

if collision_point(x,y-5,object,1,0) then s=s+1

 

 

switch (s)

{

case 2:(INSTRUKCJA);break;

case 3:(INSTRUKCJA);break;

 

}

próbowałem też zmieniać prec i notme

lecz to nie działa poprawnie, nawet taki sam układ obiektów, uruchamiany kilka razy powoduje różne rezultaty.

kod jest w Key Press Space

 

Pozdrawiam

Odnośnik do komentarza
Udostępnij na innych stronach

GML
//Funkcja LiczObj(a,b,r)

//Przyjmuje trzy argumenty

//a - id obiektu w pobliżu którego chcesz zliczyć obiekty b

//b - typ obiektu który chcesz zliczać

//r - promień w jakim chcesz zliczyć obiekty.

//Funkcja zwraca liczbę obiektów b w promieniu r od obiektu a

a=argument0;

b=argument1;

r=argument2;

licz=0;

 

with(b) //przeglądamy wszystkie obiekty b

{

if(point_distance((other.a).x,(other.a).y,x,y) <= r) //jeśli odległość mniejsza od r

other.licz+=1; //zwiększamy licznik

}

 

return licz;

Odnośnik do komentarza
Udostępnij na innych stronach

Dzięki, umieściłem ten skrypt w projekcie, w obiektach umieściłem kod

GML
s=LiczObj(self.id,object,4)

 

switch (s)

{

 

case 3:(instrukcja);break;

case 4:(instrukcja);break;

}

Lecz nadal się nie wykonuje poprawnie, nie jestem pewien czy Twój kod uwzględnia wielokrotne wystąpienie obu rodzajów obiektów.

Odnośnik do komentarza
Udostępnij na innych stronach

Uwzględnia. Wyświetl sobie przy pomocy show_message co ci ta funkcja zwraca oraz narysuj sobie w draw okrąg o tym promieniu i zobacz co jest nie tak. Pamiętaj również, że on uznaje, że obiekty są w promieniu według ich origina, a nie dowolnego fragmentu sprite'a. Jeśli chcesz by uwzględniało obiekty przecinające się z okręgiem użyj distance_to_object() zamiast point_distance()

 

I ten promień jest w pixelach. Jesteś pewien, że 4 piksele to wystarczająco? To strasznie mało.

Odnośnik do komentarza
Udostępnij na innych stronach

Chyba wiem czemu nie zadziałało mi to poprawnie, po prost GMaker nie liczy tego przecież dla wszystkich obiektów naraz tylko po kolei, i zanim w ostatnim obiekcie policzy, to obiekty, które miał liczyć mogą zniknąć, chyba zrobię to tak jak robiłem w C++ i użyję dwóch tablic, w pierwszej zapiszę układ planszy a w drugiej po obliczeniach a potem skopiuję zawartość drugiej do pierwszej.

Odnośnik do komentarza
Udostępnij na innych stronach

OK, robię automat komórkowy, mam (na razie, w projekcie więcej) 2 rodzaje komórek, reprezentują je obiekty o nazwach on i off, komórki wypełniają całą planszę według siatki, w komórkach off mam aktualnie kod:

GML
s=LiczObj(self.id,on)

 

switch (s)

{

//case 0:instance_change(off,0);break;

//case 1:instance_change(off,0);break;

//case 2:instance_change(off,0);break;

case 3:instance_change(on,1);break;

//case 4:instance_change(off,0);break;

//case 5:instance_change(off,0);break;

//case 6:instance_change(off,0);break;

//case 7:instance_change(off,0);break;

//case 8:instance_change(off,0);break;

}

W komórkach on analogicznie, aktualnie według reguł Conwaya w celu sprawdzenia czy dobrze działa.

 

Funkcję zedytowałem na następującą, gdyż makerowi.

GML
a=argument0;

b=argument1;

 

licz=0;

 

with(b)

{

//if(point_distance((other.a).x,(other.a).y,x,y) <= r)

if(distance_to_object(other.a)<= 6)

other.licz+=1;

}

 

return licz;

Odnośnik do komentarza
Udostępnij na innych stronach

Dokładnie, dla 0/1/4/5/6/7/8 sąsiadów komórka zmienia się w off

GML
s=LiczObj(self.id,on)

 

 

 

switch (s)

{

case 0:instance_change(off,0);break;

case 1:instance_change(off,0);break;

//case 2:instance_change(off,0);break;

//case 3:instance_change(off,0);break;

case 4:instance_change(off,0);break;

case 5:instance_change(off,0);break;

case 6:instance_change(off,0);break;

case 7:instance_change(off,0);break;

case 8:instance_change(off,0);break;

}

Odnośnik do komentarza
Udostępnij na innych stronach

To może ona zmienia się w on, a potem od razu w off i dlatego wychodzi, że się nie zmienia?

 

EDIT:

Chyba wiem czemu nie zadziałało mi to poprawnie, po prost GMaker nie liczy tego przecież dla wszystkich obiektów naraz tylko po kolei, i zanim w ostatnim obiekcie policzy, to obiekty, które miał liczyć mogą zniknąć, chyba zrobię to tak jak robiłem w C++ i użyję dwóch tablic, w pierwszej zapiszę układ planszy a w drugiej po obliczeniach a potem skopiuję zawartość drugiej do pierwszej.

Teraz zaczaiłem chyba co masz na myśli. I to rzeczywiście może być przyczyna. Myślałem, że mówisz o tym, że pętla with nie przeleci wszystkich obiektów na raz.

Odnośnik do komentarza
Udostępnij na innych stronach

Jakby kogoś interesowało toplik projektuWcześniej robiłem to w C++ na tablicach, lecz nie jestem aż tak bardzo zaawansowany w c++ i nie znam się zbytnio na grafice czy obsłudze klawiatury.

 

Kod C++ (jeszcze nie wiem jak pobrać od użytkownika początkowy układ więc jest zakodowany jeden w programie.)

#include <cstdlib>
  #include <iostream>
  
  using namespace std;
  
  const int wielkosc=10;
     bool plansza[wielkosc][wielkosc]=
     {   
            0,1,0,1,0,1,0,1,0,1,
            0,0,1,0,0,0,0,0,1,1,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,1,0,0,0,0,0,
            0,0,0,0,1,0,0,0,0,0,
            0,0,0,0,1,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0
     };
     
     
     
     
     
     
     bool tymczasowa[wielkosc][wielkosc]={};
      int x=0;
      int y=0;
      int k;
  
  int test()
  {int x=0;
  int y=0;
      while (y<wielkosc)
      {
          
          k=plansza[x-1][y-1]+plansza[x-1][y]+plansza[x-1][y+1]+plansza[x][y-1]+plansza[x][y+1]+plansza[x+1][y-1]+plansza[x+1][y]+plansza[x+1][y+1];
          
      
         if (plansza[x][y]==0)
         { 
           if ((k==3))
              {
              tymczasowa[x][y]=1;
              }                                      
         }
         if (plansza[x][y]==1)
         {
             if ((k==2)||(k==3))
              {
              tymczasowa[x][y]=1;  
              }
              else tymczasowa[x][y]=0;                  
                              
         }   
                
        x++;
        if (x==wielkosc)
        {  y++;
           
            x=0;
           
        }
        
      }
      y=0;
      cout<<endl;
      x=0;
      
      while (y<wielkosc)
      {
      x++;
      plansza[x][y]=tymczasowa[x][y];
        if (x==wielkosc)
        {  y++;         
           x=0;
        }
      }
  }
  
  int pokaz()
  {int x=0;
   int y=0;
    while (y<wielkosc)
      { if (plansza[x][y]==1)
      {
        cout<<"*"; 
      }
      if (plansza[x][y]==0)
      {
        cout<<" "; 
      }
         x++;
        if (x==wielkosc)
        {  y++;
           cout<<endl;
            x=0;
        }
      }
  }
  
  int main(int argc, char *argv[])
  {  int ile;
  
  system("color 0c");
  pokaz();
    UP:
     
    cout<<"Ile s wyswietlic";
    cin>>ile;
   
    while (ile>0)
    {
    system("cls");
     pokaz();
     test();
     
     
    cout<<endl;
    ile--;
    }
   goto UP;
      
      system("PAUSE");
      return EXIT_SUCCESS;
  }
  
  

Tak, wiem że nie działa poprawnie (źle liczy dla komórek krawędziowych, muszę dodać pętlę zerującą krawędź dla prawidłowego działania)v Tak, wiem że GOTO nie jest najlepsze i w tym wypadku uniemożliwia zakończenie i wszystko po nim i tak nie zadziała w tym kodzie.

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