Skocz do zawartości

[Delphi][OpenGL]Waypointy i patrzenie w kierunku


5corpio

Polecane posty

Nie mogę wykminić w czym źle pojmuje dlatego muszę napisać;) Sprawa wygląda tak: mam jakieś punkty kontrolne po, których ma chodzić postać

reprezentację waypointów i połączeń mam załatwione etc. tylko mam problem z obrotem postaci "twarzą" na wprost do nowego waypointa.

Chodzi o to, że postać dochodzi do punktu i obraca się twarzą w kierunku nowego punktu. Zaprezentuje graficznie o co kaman:

 

Obrazek

 

Czyli w momencie dojścia do pkt. (a dokładnie do małego kwadratu) muszę obliczyć kąt i obrócić postać. No i niby tak robię i coś jest źle bo się obraca o zły kąt :/

 

Teraz kod:

 procedure TSIobject.UpdateSIState;
var
 lookUpPoint : Vector2d;
begin

 { Sprawdzamy czy postać znajdzie się w kwadracie dookoła waypointa jesli tak to:}
 if PointInRect2d(Vector2(fLinkedChr.Position.x, fLinkedChr.Position.z), fLinkedPath.fTollBox) then
   begin

     { Aktualny waypoint to ten który był następny }
     fPATHcontroller := fPATHnextController;

    { A następny punkt to następny  }
     fPATHnextController := fLinkedPath.GetNextWaypoints(fPATHnextController);

     { Pobieramy pkt. w którym jest kolejny punkt i na który będziemy się mieć patrzeć }
     lookUpPoint := fLinkedPath.GetWaypoint(fPATHnextController).fData.fWPTPosition;

     { Ustawiam sobie taki mały kwadracik dookoła żeby mieć jakąś tolerancję }
     fLinkedPath.fTollBox.p1 := Vector2(lookUpPoint.x - toll, lookUpPoint.y - toll);
     fLinkedPath.fTollBox.p2 := Vector2(lookUpPoint.x + toll, lookUpPoint.y + toll);

     { Ta metoda ma obrócić postać tak żeby patrzyła prosto na żadany punkt }
     fLinkedChr.LookToPoint(lookUpPoint);
   end
     else
     begin
       lookUpPoint := fLinkedPath.GetWaypoint(fPATHnextController).fData.fWPTPosition;
       fLinkedChr.MoveForward(); // Idź na przód
     end;
end;

......

//Teraz metoda LookToPoint(...)

procedure TCharacter.LookToPoint(lookTo: Vector2d);
var
 v1, v2 : Vector2d;
 rAngle : Single;
begin
 { Pierwszy wektor zbudowany od pozycji postaci do celu patrzenia }
 v1 := Vector2(fPosition.x - lookTo.x, fPosition.y - lookTo.y);

 { Drugi wektor od postaci w dal czyli taki wektor w którą stronę idziemy }
 v2 := Vector2(fPosition.x + sin(RotateAngles.y * PI / 180), fPosition.y + cos(RotateAngles.y * PI / 180));

 { Kąt między wektorami }
 rAngle := CalcDirAngleBetween(v1, v2);

 { Pomijając pare rzeczy ta metoda działa tak: KatObrotuY = KatObrotuY + rAngle }
 RotateCharacter(rAngle);
end;

.....
//A wyliczanie kata miedzy wektorami jest (niby tak:p wg. Tostera  hehe)
function dd(const v1,v2 : Vector2d) : real;
var
  l1, l2, dProduct : real;
begin
  l1 := VectorMagnitude(v1); //dl. wektora
  l2 := VectorMagnitude(v2);
  if (l1 = 0) or (l2 = 0) then begin
     Result := 0;
     exit;
  end;
  dProduct := DotProduct(v1, v2);
  result := RadToDeg(ArcCos(dProduct / (l1 * l2)));
  if v2.y < 0 then Result := 360 - Result;
end;

function CalcDirAngleBetween(const v1, v2 : Vector2d) : real;
var
  a1, a2 : real;
begin
  a1 := dd(Vector2(1,0), v1);
  a2 := dd(Vector2(1,0), v2);
  Result := a1 - a2;
end;

 

Na koniec wrzucę programik jak ktoś ma ochotę otworzyć exe i zobaczyć jak działa dokładnie. Ten czerwony kwadrat na środku olejcie :P

Ten zielony mniejszy to jest waypoint do którego powinien dążyć postać natomiast te niebieskie linie pokazują te wyliczane wektory żeby lepiej zobrazować :)

Kursorami można dodatkowo sterować postacią. Jak się wejdzie na waypoint to się pokazuje kolejny punkt do którego powinnien podążać (dokładnie są 3 punkty)

 

Program Demonstracyjny:)

 

Jak komuś będzie się chciało zerknąć to fajnie jak nie to i tak będe drążył co jest nie ten tegez :/

 

 

Pozdro

5corpio

Ot taka mini-strona moja po godzinach :)http://www.wnetrzekuchni.pl

Link do komentarza
Udostępnij na innych stronach

W moim projekcie coś takiego wymodziłem:

       if (pZ+jason.z<=0)
       {
           if (pX+jason.x>0)
               jason.ry=RadToDeg(atan(abs(pZ+jason.z)/abs(pX+jason.x)))-90;
           else if (pX+jason.x<0)
               jason.ry=-RadToDeg(atan(abs(pZ+jason.z)/abs(pX+jason.x)))+90;
           else jason.ry=0;
       }
       else
       {
           if (pX+jason.x>0)
               jason.ry=-RadToDeg(atan(abs(pZ+jason.z)/abs(pX+jason.x)))-90;
           else if (pX+jason.x<0)
               jason.ry=RadToDeg(atan(abs(pZ+jason.z)/abs(pX+jason.x)))+90;
           else jason.ry=180;
       }

W ten sposób postać zawsze obraca się w stronę gracza (należy wziąć pod uwagę, że pX,pZ to nie jest rzeczywista pozycja postaci - niuanse z kamerą ;) - dlatego funkcji abs podaję sumę, a nie różnicę).

 

Może to Ci w czymś pomoże ;)

Link do komentarza
Udostępnij na innych stronach

Dobra problem rozwiązany wyliczam sobie innaczej kąt już a mianowicie tworze prostą potem wyliczam kąt nachylenia i lekko modyfikuje go w zależności od X :)

 

A dokładnie to tak:

   
 v1 := Vector2(lookTo.x, lookTo.y);
 v2 := Vector2(Position.x, Position.z);

 v3 := LineParamFromPoint2d(v1, v2); // Zwraca a i b prostej przechodzacej przez 2 punkty. a zapisuje do v3.x a b do v3.y 

 angl := RadToDeg(ArcTan(v3.x));
 if v1.x <= v2.x then
   angl := 90 - angl;
 if v1.x > v2.x then
   angl := 270 - angl;

 RotateCharacter(angl);

 

Jeszcze tylko zamiast dodawania kąta do aktualnego zrobiłem ustawianie na wyliczony kąt i wszystko śmiga a dokładnie łazi po punktach :)

 

Pozdro i Tyle hehe a jak ktoś jest ciekaw wyniku to tutaj jest demko z 2 postaciami korzystającymi z tej samej ścieżki: Demko]:->

Ot taka mini-strona moja po godzinach :)http://www.wnetrzekuchni.pl

Link do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

×
×
  • Utwórz nowe...