• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[SFML] Brak drgania Sprite po ruchu i kolejny wektor

Object Storage Arubacloud
+1 głos
502 wizyt
pytanie zadane 6 lutego 2016 w C i C++ przez dameg Nowicjusz (170 p.)

Witam mam następujące dwa problemy udało mi się dzięki takiej funkcji zmienić płynnie pozycję Sprite:

sf::Vector2f Robot::moveVectore(sf::Vector2f start, sf::Vector2f end, float t){
    if(start == end) return sf::Vector2f(0,0);
    // policzenie wektora przesunięcia i jego długości
    sf::Vector2f offset = sf::Vector2f(end.x - start.x, end.y - start.y);
    float length = sqrtf(offset.x * offset.x + offset.y*offset.y);
    // normalizacja wektora
    offset = sf::Vector2f(offset.x / length, offset.y / length);
    offset.x *= t;
    offset.y *= t;
    return offset;
}

Za pierwszym razem ładnie się wykonuje dzięki takiej metodzie:


        sf::Vector2f offset1 = robot1.moveVectore(robot1.getTempPositionVector(), sf::Vector2f(145,300), delta*speed);
        robot1.robot.move(offset1);

Sytuacja wygląda tak, sprite drga w miejscu minimalnie zmieniając swoją pozycje po przecinku oraz kiedy dodaje kolejny wektor i kolejny raz wykonuje move() nie działa to tak jakbym chciał czyli dochodzi do danego punktu i zmienia go na kolejny ale wychodzi poza ekran.

Jak mogę rozwiązać te problemy?

1 odpowiedź

+1 głos
odpowiedź 6 lutego 2016 przez niezalogowany
Ustal epsilon (jakiś margines błędu), który spowoduje że funkcja zakończy swoje działanie i nie będzie więcej poszuała obiektem. Tzn wykonuj funkcję tylko wtedy gdy odległość obiektu od docelowego punktu jest większa niż jakaś mała ustalona wartość np 0.5f.

@Edit btw ta funkcja wygląda podejrzanie podobnie do kodu, który kiedyś napisałem tutaj:

http://szymonsiarkiewicz.pl/poradniki/goto/podazanie-za-obiektem-w-przestrzeni-2d/
komentarz 6 lutego 2016 przez dameg Nowicjusz (170 p.)
Tak, bo jest to dokładnie sposób opisany przez Ciebie. Nadal nie wiem jednak jak po pierwszym ruchu po wektorze dodać kolejny.
komentarz 6 lutego 2016 przez niezalogowany

Nadal nie wiem jednak jak po pierwszym ruchu po wektorze dodać kolejny.

Nie rozumiem o co ci chodzi Dobra czaję, musiałem powrócić do twojego początkowego pytania, aby zgadnąć kontekst. Jak rozumiem ty chcesz osiągnąć coś takiego: obiekt porusza się do punktu A, gdy do niego dotrze to porusza się do punktu B, itd

Sprawa jest prosta i znowu wykorzystuje pomysł z epsilonem. Musisz przy poruszaniu sprawdzać czy znajdujesz się w epsilonie, jeżeli tak to zmieniasz cel na nowy.

Pseudo kod:

// gdzieś w kodzie przed wykonaniem funkcji do przemieszczenia:
if ( d(myObjectPosition, targetPosition <= epsilon) // <- d( a, b) funkcja zwracająca odległość pomiędzy punktami a i b
    tagetPosition = getNextTarget(); // ustawia nowy punkt do któego powinien kierować się obiekt

myObjectPosition = moveVectore(...);

Btw wydaje mi się, że gdzies na blogu wrzucałem kod pokazujący właśnie coś takiego, ale nie mogę znaleźć więc może mi się wydaje.

komentarz 7 lutego 2016 przez dameg Nowicjusz (170 p.)

Jest dokładnie tak jak mówisz chciałbym wykonać ruch A->B->C->D->E, pierwszy ruch działa wg. metody którą opisałeś ale nie mam pojęcia jak dodać kolejne ruchy.
Brak drgania udało się wyeliminować z użyciem epsilona.
Natomiast nie wiem jak sobie poradzić z ruchem robota. Na podstawie pseudokodu który napisałeś nie za bardzo wiem jak tego dokonać.

komentarz 7 lutego 2016 przez niezalogowany
edycja 8 lutego 2016

Załóżmy, że wszystkie punkty po których chcesz się poruszać masz w jakiejś tablicy targets = { A, B, C, D, E, ... } gdzie A, B, ... - to kolejne dwuwymiarowe wektory [x,y] przechowujące informacje o miejscu, w które powinien skierować się obiekt.

Vector2f targets[size] = ... ;
int current = 0;
Vector2f currTarget;

Vector2f getNextTarget()
{
   current = (current+1) % size;
   return targets[current];
}

Instrukcja przed wywołaniem lerpa:

// znów częściowy pseudokod
// d liczy odległość pomiędzy punktami (sam musisz zrobić implementacje d, jest trywialna)
if (d(object.position, currTarget) <= epsilon)
   currTarget = getNextTarget();

Vector2f offset = lerp(object.position, currTarget, deltaTime)

...

Tyle, tu nie ma nic trudnego. I tak dałem ci w zasadzie gotowy kod do przepisania, jedynie co musisz zrobić to lekko go zmodyfikować pod składnie SFML i napisać implementację jednej funkcji.

komentarz 7 lutego 2016 przez dameg Nowicjusz (170 p.)
Funckja:
float Robot::getDistance(sf::Vector2f vector){
    float x1 = robot.getPosition().x;
    float y1 = robot.getPosition().y;
    float x2 = vector.x;
    float y2 = vector.y;
    float distance = sqrtf(x1*x2 + y1*y2);
    return distance;
}

Lista oraz metody na ruch:

sf::Vector2f Robot::getNextTarget(){
    sf::Vector2f A(145,0);
    sf::Vector2f B(145,300);
    sf::Vector2f C(700,300);
    sf::Vector2f points[3] = {A,B,C};
    int current = 0;
    current = (current+1) % 3;
    return points[current];
}
       if (robot1.getDistance(currentTarget) <= epsilon){
            currentTarget = robot1.getNextTarget();
        }
        sf::Vector2f offset = robot1.moveVectore(robot1.tempPositionVector(), currentTarget, delta*speed);
        robot1.robot.move(offset);

Mimo to ruch jest wykonywany jedynie do pierwszego punktu...

komentarz 8 lutego 2016 przez niezalogowany

Bo źle to robisz. Spójrz u siebie na definicję funkcji getNextTarget(). W momencie wywołania wykonują sie zawsze kolejne kroki:

     sf::Vector2f A(145,0);  // <- tworzysz punkt A
    sf::Vector2f B(145,300); // tworzysz punkt B
    sf::Vector2f C(700,300); // tworzysz punkt C
    sf::Vector2f points[3] = {A,B,C}; // tworzysz tablicę zawierającą te punkty, btw co za marnotractwo pamięci i czasu, ta linia i powyższe powinny znaleźć się w konstruktorze, a sama tablica lub jakiś kontener na dane w pliku .h klasy
    int current = 0; // tworzysz zmienną currrent i ustawiasz ja zawsze na 0, ŹLE! powinna być w pliku .h, linia =0 powinna być w np konstruktorze
    current = (current+1) % 3;
    return points[current];

Jak mówiłem: kod wystarczyło przepisać, ale znowu potwierdza się to co w zasadzie wiedziałem i o czym wspominał @Comandeer w swojej recenzji: sporo ludzi na tym forum nie potrafi przepisać poprawnie kodu.

I to nie jest tak, że ten problem jest wybitnie trudny, wystarczy myśleć przy przepisywaniu kodu.

komentarz 8 lutego 2016 przez dameg Nowicjusz (170 p.)
W takim razie gdzie jest błąd dokładnie i jak go poprawić aby to w końcu zadziałało? Szczerzę mówiąc nie wiem na jakiej zasadzie funkcja getNextTarget podaje tutaj następny wektor.
komentarz 8 lutego 2016 przez niezalogowany

W takim razie gdzie jest błąd dokładnie i jak go poprawić aby to w końcu zadziałało?

Przecież napisałem w komentarzach do kodu, czytasz to co piszę?

// tworzysz zmienną currrent i ustawiasz ja zawsze na 0, ŹLE! powinna być w pliku .h, linia =0 powinna być w np konstruktorze

Twoim problemem jest, że nie rozumiesz tego co się dzieje w bądź co bądź bardzo prostym kodzie, nawet po kursie MZ (podstaw i obiektówki) powinieneś wiedzieć co się dzieje. Funkcja tego typu:

// gdzieś w kodzie
int index = ... ;
Object objects[size] = { ... } ;

// def funkcji
Object getNextElement()
{
   index = (index+1) % size;
   return objects[index];
}

to podstawy podstaw (aby zrozumieć ten kod wystarczy rozumieć jak działają funkcje, operatory i tablice) i jeżeli nie wiesz co się w niej dzieje to powinieneś powrócić do kursu podstawowego (np na cpp0x.pl ) i go dokładnie przerobić, jeżeli czepiasz się gamedev'u to musisz mieć już jakąś wiedzę inaczej to nie ma sensu.

Podobne pytania

0 głosów
2 odpowiedzi 250 wizyt
pytanie zadane 8 stycznia 2017 w C i C++ przez Staszek Gorycki Nowicjusz (170 p.)
0 głosów
2 odpowiedzi 399 wizyt
pytanie zadane 28 grudnia 2016 w C i C++ przez Staszek Gorycki Nowicjusz (170 p.)
0 głosów
1 odpowiedź 323 wizyt

92,661 zapytań

141,554 odpowiedzi

319,995 komentarzy

62,028 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...