podążanie z punktu A do punktu B

0

Mam prośbę! Męczę się już jakiś czas z przemieszczaniem - podążaniem jednego obiektu do drugiego w 2D przy zastosowaniu Timera. Powiedzmy, że są to obiekty TShape. Chodzi mi, aby jeden dogonił drugiego z możliwością zmiany współczynnika szybkości jednego z tych obiektów (przyśpieszenie lub zwolnienie). Z tego co osiągnąłem do tej pory to na ogół ucieka mi jedna z osi albo x albo y, w tym sensie, że szybciej się zrównuje i później goni tylko po jednej osi. Przeglądnąłem już sporo stron jakoś nic nie znalazłem, co by rozwiązało ten problem. Pewnie źle interpretuję wzory - ale nigdy nie byłem orłem z matmy :-P Może ktoś zna jakąś stronę, albo ma przykładowy kod. Niewątpliwie dla wielu z was to pestka, a ja się z tym męczę.

0

jak bys pokazal swoj kod to moglo by byc latwiej... moze wystarczy cos przerobic, a tak zmuszasz nas do pisania wszystkiego od nowa...

0

Jest kilka wersji:
1.
...
function Interp_Linear(const vA, vB: Single; t: Single): Single;
begin
result := vA + (vB - vA) * t;
end;

...
wywolanie
x := 0.3; //wartosc przykladowa
S.Left := Round(Interp_Linear(S1.Left, S2.Left, x));
S.Top := Round(Interp_Linear(S1.Top, S2.Top, x));

x przejmuje wartosc w przedziale <0:1> ale jeżeli spadnie poniżej pewnej wartości - bodajrze = S1 / S2 (zakładając, że S1 < S2) punkt nie dobije do drugiego i sie zatrzyma - ciekawy przypadek. Jak ma tyle co trzeba to pedzi za szybko, bardzo szybko, ale widać dlaczego - zbyt duze wartosci przy zmianie. Ale ma tez jeden + zwalnia przy dobijaniu do celu :-) Fajny efekt :-)

function Interpolacja(X1,Y1, X2,Y2, X : Double) : Double;
{ interpolacja liniowa }
var
a, b : Double;
begin
{ współczynnik kierunkowy prostej }
a := (Y2 - Y1) / (X2 - X1);
{ parametr b }
b := ((-X1) * (Y2 - Y1) - (X2 - X1) * (-Y1)) / (X2 - X1);
Interpolacja := a * X + b;
end;

Tutaj problem z X przy wywołaniu, chyba musi być zmienny. Jak taki robię to pojawia się problem jak we wstępie.

if (S.Top <> S2.Top) and (S.Left <> S2.Left) then begin

  a := (S.Top-S2.Top)/ (-1*S2.Left+S.Left) ;
  b := S.Top - S.Left * a ;
  if (S.Left < S2.Left) then S.Left := S.Left + 1 ;
  if (S.Left > S2.Left) then S.Left := S.Left - 1 ;

  y0 := a*S.Left+b;
  S.Top := Round(y0);
end;

if (l >= 1) then begin
S2.Left := S2.Left + 1;
S2.Top := S2.Top + 1;
l := 0;
end;</span>

Ten sposób wymąciłem sam ze wzorów matematycznych jeszcze na samym początku zanim znalazłem 1 i 2 w necie. Problem jak na wstępie. Za szybko wyrównuje jedną oś.

We wszystkich przypadkach podążają do celu ale jakoś nie tak jak mają ;-) Rozumiecie o ca chodzi ;-) Proszę tylko o wyrozumiałość względem niedoskonałości kodu to są wersje robocze - na próbę, a poza tym jestem jeszcze zielony w te klocki ;-)

0

ja to widze tak:
dwie zmienne globalne, musisz im przypisac poczatkowe wspolrzedne przed rozpoczeciem "animacji"...

  dx,dy:Real;
procedure TForm1.Timer1Timer(Sender: TObject);
var x,y:Integer;
    w,h:integer;//odleglosci poziome i pionowe pomiedzy punktami a i b
    from,dest:TPoint;
begin
 from:=Point(Shape1.Left, Shape1.Top);
 dest:=Point(Shape2.Left, Shape2.Top);

 w:=(from.x - dest.x);
 h:=(from.y - dest.y);

 dx:=dx+(  (-w)/100  ); //linia zostanie narysowana w 100 krokach
 dy:=dy+(  (-h)/100  ); //mozesz tym regulowac szybkosc rysowania

 x:=Round(dx);
 y:=Round(dy);

 form1.Canvas.LineTo(x,y);

 if (abs(from.x-x)>Abs(w)) or (abs(from.y-y)>Abs(h)) then
    begin
      Timer1.Enabled:=false;
      beep;
    end;
end;

z tego co sprawdzilem to dziala we wszystkich kierunkach.
jedynym minusem jest to, ze przy szybkim ruchu krok bedzie wynosil np 10px, wiec Twoj shape moze sie zatrzymac nawet 10 czy tam 9px dalej niz powinien, ale mysle ze nie bedzie z tym problemu zeby to poprawic.

dodatkowym plusem jest to, ze znajac interval timera oraz wiedzac w ilu krokach bedzie narysowana linia (czy tez przemieszczony obiekt), wiesz ile dokladnie czasu to zajmie.

P.S. w sumie to zmienne from,dest,w,h oraz obliczenia z nimi zwiazane tez mozna dac jako globalne... bez sensu zeby sie wiele razy to samo wykonywalo. wystarczy raz, przed rozpoczeciem animacji.

0

Dzięki za zainteresowanie i pomoc. Widzę, że wyszedłeś od koncepcji 1. Zastosowałem się do twoich poleceń i sprawdziłem kod na szybko i widzę, że aby zachować ten sam krok dane początkowe (startowe) obiektu podążającego muszą być przypisane poza animacją, w trakcie animacji nie mogą ulegać zmianie. Na dokładniejszą analizę i pracę nad tym kodem będę miał czas dopiero za dwa dni - inne obowiązki niestety. Jeszcze raz dzięki i liczę na dalsze zainteresowanie ;-)

1 użytkowników online, w tym zalogowanych: 0, gości: 1