#include <SFML/Graphics.hpp>
using namespace sf;
const int rozmiarOknaX=1200;
const int rozmiarOknaY=800;
const int rozmiarTablica=2500;
const float dzielnikPredkosc=2000000;
const Vector2f prostokatPoczatek(400,400);
const Vector2f prostokatRozmiar(400,200);
const int liczbaPrzeszkodStala=1;
class mucha;
class przeszkody
{
friend mucha;
private:
int liczbaPrzeszkod=liczbaPrzeszkodStala;
RectangleShape listaPrzeszkod[liczbaPrzeszkodStala];
public:
przeszkody();
RectangleShape* wyslijTablice ();
int wyslijLiczbaprzeszod();
RectangleShape wyslijNtaPrzeszkode(int);
};
class mucha : public CircleShape
{
private:
int licznik=0;
Vector2f polozenie;
Vector2f predkosc;
Vector2f tablicaPredkosc[rozmiarTablica];
bool czyZyje;
public:
przeszkody wszystkiePrzeszkody; //ma byc static
mucha();
void aktualizuj();
friend bool czyKolizja(RectangleShape przeszkody[], int liczbaprzeszkod, Vector2f polozenie);
};
int przeszkody::wyslijLiczbaprzeszod()
{
return liczbaPrzeszkod;
}
RectangleShape przeszkody::wyslijNtaPrzeszkode(int n)
{
return listaPrzeszkod[n];
}
przeszkody::przeszkody()
{
for(int i=0; i<liczbaPrzeszkod;i++)
{
listaPrzeszkod[i].setSize(prostokatRozmiar);
listaPrzeszkod[i].setPosition(prostokatPoczatek);
}
}
RectangleShape* przeszkody::wyslijTablice()
{
return listaPrzeszkod;
}
bool czyKolizja(RectangleShape* przeszkody, int liczbaPrzeszkod, Vector2f polozenie)
{
for(int i=0; i<liczbaPrzeszkod; i++)
{
if(polozenie.x>przeszkody[i].getPosition().x&&
polozenie.x<przeszkody[i].getPosition().x+przeszkody[i].getSize().x&&
polozenie.y>przeszkody[i].getPosition().y&&
polozenie.y<przeszkody[i].getPosition().y+przeszkody[i].getSize().y)
return false;
}
return true;
}
mucha::mucha():polozenie(rozmiarOknaX/2,100), predkosc(0,0.25), czyZyje(true)
{
for(int i=0; i<rozmiarTablica; i++)
{
tablicaPredkosc[i].x=(rand()%2==0?1:-1)*rand()/dzielnikPredkosc; //zastapic funkcja losuj
tablicaPredkosc[i].y=(rand()%2==0?1:-1)*rand()/dzielnikPredkosc;
}
setRadius(5);
setOrigin(2.5, 2.5);
setPosition(polozenie);
}
void mucha::aktualizuj()
{
if(licznik<rozmiarTablica&&czyZyje)
{
setPosition(polozenie+=predkosc); //zmienia polozenie a potem wysyla do funkcji setPosition
predkosc+=tablicaPredkosc[licznik];
}
czyZyje=czyKolizja(wszystkiePrzeszkody.wyslijTablice(), wszystkiePrzeszkody.liczbaPrzeszkod, polozenie);
licznik++;
}
int main()
{
srand( time( NULL ) );
RenderWindow okno(VideoMode(rozmiarOknaX, rozmiarOknaY), "SFML window");
mucha mucha1;
while (okno.isOpen())
{
Event event;
while (okno.pollEvent(event))
{
if (event.type == Event::Closed)
okno.close();
}
okno.clear();
okno.draw(mucha1);
for(int i=0; i<mucha1.wszystkiePrzeszkody.wyslijLiczbaprzeszod(); i++)
okno.draw(mucha1.wszystkiePrzeszkody.wyslijNtaPrzeszkode(i));
// Update the window
okno.display();
mucha1.aktualizuj();
}
return EXIT_SUCCESS;
}
, mniej więcej w nim chodzi o to, żeby pokazać zastosowanie algorytmu genetycznego na podstawie much, które próbują dolecieć do celu, omijając po drodze przeszkody, do zobrazowania tego użyłem SFML, lecz nie w tej bibliotece robi problem.
Jest funkcja zaprzyjaźniona czyKolizja która po prostu sprawdza czy mucha nie uderzyła w przeszkodę. Jest ona wywoływana przez metodę klasy Mucha, aktualizuj. Żeby tą funkcję wywołać z jednym z argumentów listaprzeszkód musiałem umieścić egzemplarz w klasie mucha. Jednak nie chcę, żeby każdy egzemplarz klasy mucha tworzył nowy identyczny egzemplarz klasy przeszkody, więc chciałem ten egzemplarz przeszkody w klasie mucha oznaczyć jaki static. Jednak wtedy wyskakują mi błędy, gdy chcę się odwołać do niego.
Dziękuję za jakąkolwiek pomoc, gdyż z tym problemem siedzę 2 dni i nie mam pomysłu jak go rozwiązać.
Edit. Jakby ktos znał lepsze rozwiązanie mojego problemu to też bym prosił o jakieś wskazówki:)
To dość powszechny problem, powinieneś poszukać trochę w Sieci - na pewno byś znalazł .
Ze wskazówkami jest tak, że w końcu za bardzo poprawiony przez kogoś kod umyka naszemu zrozumieniu . Kilka rzeczy można by tu usprawnić, np.:
utworzyć klasę Okno czy UkladWspolrzednych, która "zaopiekuje" się tymi wszystkimi zmiennymi globalnymi
unikałbym przyjaźni - po to mamy składowe prywatne, by nikt obcy ich nie dotykał; położenie można udostępnić publiczną metodą
wszystkiePrzeszkody lepiej byłoby przenieść do osobnej klasy (wtedy zmienna statyczna nie byłaby potrzebna) - żadna mucha nie przenosi ze sobą przeszkód
wydaje mi się, że rozsądniej byłoby utworzyć klasę abstrakcyjną Obiekt i sprawdzać kolizje między obiektami tej klasy (po niej dziedziczyłaby i klasa Mucha, i klasa Przeszkoda); nie chcę się mądrować, bo mało wiem na temat samych kolizji - poszukaj jakiegoś tutoriala, gdzie jest to zrobione dobrze
wyslijNtaPrzeszkode można by zamienić na przeciążony operator[]
Z kolizjami to wszystko zależy od tego, co będzie "latać". Jeśli będziesz mieć jeden (ewentualnie dla więcej niż jednego można zrobić jakąś klasę bazową dla klas mucha i przeszkoda jak wyżej, by uwzględniać też inne obiekty klasy mucha) obiekt klasy mucha, najrozsądniej chyba będzie dodać do tej klasy (zamiast zaprzyjaźniać funkcję z zewnątrz) metodę:
Dzięki za kolejne rady,nie wiem jak Ci się odwdzięczę, powinienem móc klikać za każdą Twoją odpowiedź z 5 razy pomógł nie wiem czy aż tak bym rozwijał ten programik, bo w sumie ma tylko demonstrować algorytm genetyczny, oczyszczę kod na pewno, ale chyba klasy bazowej dla much i przeszkód nie będę robił, choć przy kolejnym programem z SFLM na pewno zacznę od pisania klasy bazowej I o range-based for słyszałem, ale weszła ta pętla w C11 i odruchowo piszę zwykłego fora
Jestem już przy końcu działającej wersji, mam tylko problem z samą końcówka, więc jakbyś odpowiedział mi na parę pytań (lub ktoś inny byłbym niezmiernie wdzięczny)
Wiem, że jakość kodu nie poraża, Twoje rady jeszcze czekają na zastosowanie, ale bardzo chciałym zobaczyć działającą wersję, a potem oczyścić kod.
Tu dwa problemy które już sam rozwiązałem, więc nie warto czytać :
Ukryta treść:
Problem mam z funkcją sort(z biblioteki standardowej) i krzyzuj.
1. Funkcja sort działa dla małej ilości much, np. 10 bez żadnego błędu, lecz dla większej ilości much wyrzuca albo bad alloc albo jakiś błąd z numerem z kosmosu.
2. Funkcja krzyzuj (linia 186) te same błędy wyrzuca, jednak dla każdej ilości much. Gdy dodałem asercje w pierwszej linijce tej funkcji, to wykonanie kodu nie doszło do niej, więc problem jest już przy wywołaniu(oczywiscie funkcje sort wykomentowałem)
Przeglądałem informacje o funcji sort, lecz albo jestem ślepy, albo nie ma nic o moim problemie
Edit Z sort sobie poradziłem, zamiast probować szukać w opisie wpisałem sort+bad alloc C++ i na stackoverflow znalazłem w pierwszym linku, z krzyżuj dzieją się dziwne rzeczy dla 50 much nie działa, dla 500 działa, ale nic nie robi, albo nie widzę efektów.Edit 2 Z krzyzuj przy wowyłaniu był problem z zakresem tablic, muszę wreszcie zmusić się do używania vectora, bo on ma automatyczne sprawdzenie zakresów
Mam też następujący problem, ale on tyczy się już SFLM, więc jeśli w nim nie siedziałeś, to nie chcę Ci zajmować czasu, bardziej liczę na osoby, które używały tej biblioteki (chyba, że też Łukasz używałeś go )poza funkcjami inicjować zmienne można tylko przy deklaracji/definicji.
Jednak mam taki problem, że chcę mieć globalną tablicę Vector2f, jednak przy probie inicjalizacji dostaje zwrotną informację od kompilatora, że nieudana konwersja z int do Vector2f, jak sobie z tym poradzić.
Tutaj jest działająca wersja, maluje najlepsze muchy na czerwono (w funkcji krzyżuj) i zauważyłem, że wcale nie te najlepsze muchy są malowane na czerwono, czyli funkcja sort nie sortuje, masz pomysł dlaczego? Z góry dziękuję
Co do sortowania, wyświetl wyliczane oceny, to szybko zauważysz przyczynę problemu. Z tego, co widzę, wszystkie muchy od pewnego momentu mają ocenę \(\displaystyle{ 600}\) (nie zagłębiałem się w kod, może one gdzieś tam giną, ale i tak ocena przyjmuje tylko dwie wartości: \(\displaystyle{ 0}\) i \(\displaystyle{ 600}\), na tej podstawie nie można ich posortować).
Dzięki jeszcze raz, jawny konstruktor zadziałał, nie pomyślałem o tym, jeszcze dużo mi brakuje.
Mam ostatnie pytanie, bo już wszystko działa, poza jedną rzeczą, w pierwszej turze sortowanie nie działa. Gdy wypisuje ocenę w aktualizuj() to wszystko jest ok, ale jak po sortowaniu w main, to mam opóźnienie i najpierw same zera wypisuje, masz jakiś pomysł? Jeszcze raz dziękuję
wypisuj wartości zmiennych w jednym miejscu lub pod spójnym warunkiem, np. określonym przez wynik jakiejś funkcji (mam na myśli if z wywołaniem funkcji zaraz przed wypisaniem wartości; możesz też przeanalizować program jakimś debuggerem i tam ładnie podejrzeć wartości poszczególnych zmiennych)
oznaczaj w jakiś specjalny sposób składowe klas, np. przedrostkiem m_, _ lub przyrostkiem _; dużo łatwiej czyta się wtedy kod - wiadomo, czy w danym miejscu zmieniamy wartość składowej jednego obiektu, drugiego, zmiennej lokalnej zdefiniowanej trzydzieści linijek wyżej czy zmiennej globalnej z innego pliku