Autor Wątek: poruszenie sprita z punktu A do B  (Przeczytany 1111 razy)

Offline zajmundov

  • Użytkownik

# Grudzień 17, 2016, 22:47:57
witajcie przywoływacze!
potrafię już w SDL'u poruszać spritem strzałkami góra, dól, lewo i prawo :) chciałbym teraz aby mój sprite zaczął się ruszać w kierunku gdzie nacisnę myszką. Np. naciskam LPM w miejscu x = 150, y 130 i chciałbym aby zaczął się tam poruszać z wyznaczaną mu wcześniej predkością. Czy ma ktoś jakiś gotowy kod? :P Wiem, że bez kilku funkcji matematycznych nie obejdzie się...
« Ostatnia zmiana: Grudzień 17, 2016, 22:49:30 wysłana przez zajmundov »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline JasonVoorhees

  • Użytkownik
    • The Immortal Life of the Son of Jay

# Grudzień 18, 2016, 01:22:10
1) Wektor kierunkowy otrzymasz odejmując pozycję sprite'a od pozycji kliknięcia, wynikowy wektor normalizujesz.

2) Znormalizowany wektor mnożysz przez prędkość z jaką sprite ma się poruszać oraz czas klatki i o tą wartość zwiększasz obecne położenie sprite'a.

3) Kiedy sprite osiągnie pozycję kliknięcia, to kończysz jego przesuwanie.
« Ostatnia zmiana: Grudzień 18, 2016, 01:24:04 wysłana przez JasonVoorhees »

Offline Patrulek

  • Użytkownik

  • +1
# Grudzień 18, 2016, 01:58:26
Podejrzewam, że posiadasz pętlę czasu rzeczywistego, która ogranicza Ci jakoś prędkość programu do np. 60 klatek na sekundę?

SDL_Event event;

if( SDL_PollEvent(&event) ) {
  if( event.type == SDL_MOUSEBUTTONDOWN ) {
    Vec2D delta = target_pos - player_pos; // Na początek obliczasz wektor pomiędzy celem, a obiektem

    float obj_target_dist = delta.magnitude(); // Math.sqrt(delta.x * delta.x + delta.y * delta.y) ... obliczasz odległość obiektu od celu, aby przechować później tę wartość w obiekcie
   
    delta.normalize(); // delta /= delta.magnitude() ... normalizujesz wektor delta, będziesz wiedział ile musisz się przemieścić na osi x, oraz na osi y aby przemieścić się o 1 jednostkę

    Vec2D velocity = delta * player.speed * Time.deltaTime ; // wektor prędkości obiektu

    player.velocity = velocity; // nadajesz prędkość graczowi
    player.player_target_dist = obj_target_dist; // nadajesz odległość jaką musi pokonać; można by to obliczać co klatkę, ale w sumie po co ;)
  }
}

void player::move() {
  player_target_dist -= velocity.magnitude();

  if( player_target_dist > 0 )  { // jeszcze nie doszliśmy do celu
    pos += velocity;
  } else { // przeszliśmy za daleko
    float ratio = (velocity.magnitude() + player_target_dist) / velocity.magnitude(); // musimy obliczyć przez jaki ułamek przemnożyć prędkość aby nie przejść za daleko celu
    pos += velocity * ratio;

    velocity = Vec2D.ZERO; // zerujemy wektor prędkości, doszliśmy do celu
    player_target_dist = 0;
  }
}

@edit
Jason mnie ubiegł, aczkolwiek dałem trochę bardziej szczegółowe wyjaśnienia ;)

@edit2
Poprawiono.
« Ostatnia zmiana: Grudzień 18, 2016, 13:09:18 wysłana przez Patrulek »

Offline Kyroaku

  • Użytkownik

  • +1
# Grudzień 18, 2016, 02:39:36
Cytuj
Podejrzewam, że posiadasz pętlę czasu rzeczywistego, która ogranicza Ci jakoś prędkość programu do np. 60 klatek na sekundę?
Ta, bo jak ktoś zaczyna naukę, to pierwsze co robi, to zaczyna od pętli czasu rzeczywistego, liczenia fps'ów i ich ograniczania. Ludzie, trzymajcie mnie.

Cytuj
float obj_target_dist = delta.magnitude(); // Math.sqrt(delta.x * delta.x + delta.y * delta.y) ... obliczasz odległość obiektu od celu i przechowujesz tę wartość w obiekcie
   
    delta.normalize(); // float max = Math.max(delta.x, delta.y); delta.x /= max; delta.y /= max; ... normalizujesz wektor delta, będziesz wiedział ile razy na 1 jednostkę x musisz się przemieścić na osi y (albo na odwrót, zależy od tego czy delta.x jest większe, czy delta.y)

    float delta_dist = delta.magnitude(); // obliczasz jaką odległość pokonasz po jednym przesunięciu obiektu przez wektor delta (już znormalizowany)

    float translation = player.speed * Time.deltaTime; // mając prędkość obiektu obliczasz jaką odległość pokona w jednej klatce, Time.deltaTime dla 60 klatek = ~16ms

    float ratio = translation / delta_dist; // obliczasz ile razy zmieści musisz przesunąć obiekt o znormalizowany wektor aby przenieść o dystans jaki pokona w jednej klatce
    Vec2D velocity = ratio * delta; // ostateczny wektor prędkości obiektu
"Kto sam nie umie, ten uczy", czy jakoś tak.

« Ostatnia zmiana: Grudzień 18, 2016, 02:46:14 wysłana przez Kyroaku »

Offline zajmundov

  • Użytkownik

# Grudzień 18, 2016, 12:53:26
pętlę i czas delta mam. Będę musiał poszukać w internecie klasę vector 2d, a potem powoli zacznę kopiować wypociny

Offline Patrulek

  • Użytkownik

# Grudzień 18, 2016, 13:01:04
Cytuj
Ta, bo jak ktoś zaczyna naukę, to pierwsze co robi, to zaczyna od pętli czasu rzeczywistego, liczenia fps'ów i ich ograniczania. Ludzie, trzymajcie mnie.

OP napisał, że ma już poruszanie za pomocą strzałek, jakąś pętlę musi mieć do sprawdzania wystąpienia eventów klawiszy. Mam się domyślić, czy ogranicza jakoś czas? Przyjąłem takie założenie, a nie inne, jeśli się okaże, że autor nie ma takiej pętli to po prostu się uzupełni wypowiedź, ludzie trzymajcie go.

Co do kodu, widzę błąd, zaraz poprawię. Obliczeniowo jest poprawnie, ale złe nazewnictwo się wkradło. Pewnie godzina zrobiła swoje i trochę przekombinowałem.

Offline Xion

  • Redaktor
    • xion.log

  • +1
# Grudzień 18, 2016, 18:48:01
Ta, bo jak ktoś zaczyna naukę, to pierwsze co robi, to zaczyna od pętli czasu rzeczywistego, liczenia fps'ów i ich ograniczania. Ludzie, trzymajcie mnie.
Jeśli od tego nie zacznie (może poza liczeniem FPSów), to specjalnie daleko nie zajdzie...

Offline zajmundov

  • Użytkownik

# Grudzień 24, 2016, 02:09:39
Muszę napisać sobie klasę Entity i dopisać funkcje odpowiedzialne za poruszanie się
dzięki ogólnie za pomóc