Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Aşağıdan Yukarıya Eğik Atış
#1
Merhaba
Firemonkey ile geliştirdiğim bir uygulama için nesneleri aşağıdan yukarıya eğik atış biçiminde fırlatmak istiyorum. Yaklaşık 2 saatlik bir uğraş sonucu aşağıdaki kodlardaki yapıyı kurdum. Vcl tarafında sorun yok ama mobilde istediğim performansı alamıyorum. Ve Peş peşe atışlar yaptıramıyorum. Sonra attığım öncekini bekliyor. Açıkcası ilk başta animationlarla yapmaya çalıştım fakat çok vakıf olmadığım için beceremedim. Proje test kodlarını paylaşıyorum. Şu anki yapı içime sinmedi asıl soru bunu animationlarla nasıl yaparız.

LİNK : Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.

unit Unit1;

interface

uses
 System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Objects,Math;


type
 TTopOlustur = record
   TopParent    : TPaintBox;
   TopRenk      : TAlphaColor;
   TopSize      : Integer;
   TopLeft      : Integer;
   TopTop       : Integer;
   NamluUzunluk : Integer;
   NamluAci     : Extended;
   YerCekimi    : Extended;
   IlkHiz       : Extended;
   TopGidisHizi : Extended;
end;

type
 TFrmTest = class(TForm)
   BtnTest: TButton;
   PaintBox1: TPaintBox;
   procedure BtnTestClick(Sender: TObject);
 private
   procedure TopOlustur(xParam: TTopOlustur);
 public
   { Public declarations }
 end;

var
 FrmTest: TFrmTest;

implementation

{$R *.fmx}

{ TForm1 }

procedure TFrmTest.BtnTestClick(Sender: TObject);
var
 xParam : TTopOlustur;
begin
with xParam do
 begin
   TopParent    := PaintBox1;
   TopRenk      := TAlphaColorRec.Crimson;
   TopSize      := 20;
   TopLeft      := 10;
   TopTop       := Self.ClientHeight-20-Trunc(BtnTest.Height);
   NamluUzunluk := 60;
   NamluAci     := 40;
   YerCekimi    := 100;
   IlkHiz       := 22;
   TopGidisHizi := 0.05;
 end;
 TopOlustur(xParam);
end;

procedure TFrmTest.TopOlustur(xParam: TTopOlustur);
var
 xTop                             : TCircle;
 v2,vAv                           : Extended;
 a, vx, vy, vy1, vy2, x, y, nexty : Extended;
 temp                             : Extended;
 Barrellength                     : Extended;
 dx,dy                            : Extended;
 SinTheta, CosTheta               : Extended;
 TimeInc                          : Extended;
 InBarrel                         : Boolean;
 stopped                          : Boolean;
 firstout                         : Boolean;
 barreltop                        : TPoint;
 TopRadius                        : Integer;
 TopLeft                          : Integer;
 TopTop                           : Integer;
 TopSize                          : Integer;
 MaxLevel                         : Integer;
 Theta                            : Extended; // Teta
 Gravity                          : Extended; // Yer Çekimi
 IlkHiz                           : Extended; // Başlangıç Hızı
 Origin                           : TPoint;   // Top Orjini
 p1,p4                            : TPoint;   // Temp Point
 IlkKonum                         : TPoint;   // İlk Konumlar
 NamluUzunluk                     : Integer;  // Namlu Uzlunluğu

 function Fn_Mesafe(p1,p2:TPoint):Extended; // Mesafeyi Verir
 begin
   result             := Sqrt(Sqr(p1.x-p2.x)+Sqr(p1.y-p2.y));
 end;

 procedure TopKonumAyarla;                  // Topun Konumu Ayarlanır
 begin
   application.processmessages;
   xTop.Position.X := TopLeft;
   xTop.Position.Y := TopTop;
 end;

 procedure Yenile;                          // Topu Namluya Doldurur Yeniler
 begin
   application.processmessages;
   TopLeft            := IlkKonum.x;
   TopTop             := IlkKonum.y;
   TopKonumAyarla;
 end;

 procedure IlkKurulum;
 var
   w                  : Integer;
   a                  : Extended;
    procedure rotate(var p:Tpoint; a:Extended);
    var
      t   :  TPoint;
    begin
      t   := P;
      p.x := Trunc(t.x*cos(a)-t.y*sin(a));
      p.y := Trunc(t.x*sin(a)+t.y*cos(a));
    end;
    procedure translate(var p:TPoint; t:TPoint);
    Begin
      p.x := p.x+t.x;
      p.y := p.y+t.y;
    end;
 begin
   xTop              := TCircle.Create(xParam.TopParent); // Parametre Top Parenti
   xTop.Visible      := False;
   xTop.Parent       := xParam.TopParent;                 // Parametre Top Parenti
   xTop.Size.Width   := xParam.TopSize; // Parametre Top Size
   xTop.Size.Height  := xParam.TopSize;// Parametre Top Size
   xTop.Fill.Color   := xParam.TopRenk; // Parametre Top Renk
   xTop.BringToFront;
   TopLeft           := xParam.TopLeft;  // Parametre Top Left
   TopTop            := xParam.TopTop; // Parametre Top Top
   TopSize           := xParam.TopSize;  // Parametre Top Size
   Origin.x          := TopLeft + TopSize div 2;
   Origin.y          := TopTop  + TopSize div 2;
   application.processmessages;
   IlkKonum.x        := TopLeft;
   IlkKonum.y        := TopTop;
   TopRadius         := TopSize div 2;
   NamluUzunluk      := Trunc(xParam.NamluUzunluk); // Parametre Namlu Uzlunluk
   theta             := DegToRad(xParam.NamluAci);       // Parametre Namlu Açı
   w                 := TopSize div 2;
   a                 := xParam.NamluAci;                 // Parametre Namlu Açı
   p1                := point(-w,w);
   p4                := point(NamluUzunluk,+w);
   rotate(p4,a);
   translate(p4,origin);
   rotate(p1,a);
   translate(p1,Origin);
   MaxLevel          := p1.y;
 end;

 function Fn_TopEkrandaMi:boolean;
 var
   ballcenter    :  TPoint;
 begin
   Result        := False;
   If not inbarrel then Exit;
   if barrellength<TopRadius then
     Result      := False
   else
   begin
     ballcenter  := Point(TopLeft+TopRadius,TopTop+TopRadius);
     Result      := (Fn_Mesafe(IlkKonum,ballcenter) < barrellength);
     inbarrel    := Result;
   end;
 end;
Begin
 IlkKurulum;
 try
   Yenile;
   xTop.Visible    := True;
   sinTheta        := sin(theta);
   costheta        := cos(theta);
   Barrellength    := Fn_Mesafe(p1,p4);
   barreltop.y     := Origin.y-round(barrellength*sintheta);
   barreltop.x     := Origin.x+round(barrellength*costheta);
   x               := TopLeft;
   y               := TopTop;
   Gravity         := xParam.YerCekimi/100; // Parametre Yer Çekimi
   a               := -Gravity*sin(theta);
   IlkHiz          := xParam.IlkHiz;      // Parametre Power
   timeinc         := xParam.TopGidisHizi;     // Parametre Top Gidiş Hızı Slow Bununla ayarlanır
   Vx              := IlkHiz*costheta; //x yönünde hız
   vy              := IlkHiz*sintheta; //y yönünde hız
   VAv             := IlkHiz;
   dx              := Vx*timeinc;
   dy              := Vy*timeinc;
   firstout        := True;
   stopped         := False;
   inBarrel        := True;
   repeat
     if Fn_TopEkrandaMi then
     begin
       v2          := IlkHiz+a*timeinc;
       vAv         := (IlkHiz+v2)/2;
       vx          := vAv*costheta;
       vy          := vAv*sintheta;
       dx          := vx*timeinc;
       dy          := vy*timeinc;
       x           := x+dx;
       y           := y-dy;
       TopLeft     := round(x);
       TopTop      := round(y);
       if (v2<=0) and ((TopLeft<IlkKonum.x) or (TopTop>IlkKonum.y)) then
       begin
         stopped   := True;
         TopLeft   := IlkKonum.x;
         TopTop    := IlkKonum.y;
       end;
       IlkHiz      := v2;
     end
     else
     begin
       if firstout then
       begin
         firstout    := False;
         a           := -xParam.YerCekimi/100; // Parametre Yer Çekimi
         vy1         := vy;
       end;
       temp          := vy1+a*timeinc;
       vy2           := temp;
       vy            := (vy1+vy2)/2;
       dy            := vy*timeinc;
       nexty         := y-dy;
       If vy2<=0 then
       begin
         if (nexty>MaxLevel-TopSize)
         then
         begin
           TopTop    := MaxLevel-TopSize;
           stopped   := true;
         end
         else
         begin
           y:=nexty;
           TopTop    := round(y);
         end;
       end
       else
       begin
         if (nexty<0) then
         begin
           dy        := 0;
           vy2       := -vy1;
           If xParam.YerCekimi=0 then stopped := True; // Parametre Yer Çekimi
         end
         else
         begin
           y         := nexty;
           TopTop    := round(y);
         end;
       end;
       if x+dx> xParam.TopParent.Width then // Parametre Top Parent Width
       begin
         TopLeft     := Trunc(xParam.TopParent.width) - TopSize; // Parametre Top Parent Width
         TopTop      := MaxLevel-TopSize;;
         stopped     := True;
       end
       else
       begin
         x           := x+dx;
         TopLeft     := round(x);
       end;
       vy1:=vy2;
       //Top Nereye geldi burada hesaplanacak..
     end;
     TopKonumAyarla;
     application.processmessages;
   until stopped;
 finally
   xTop.DisposeOf;
 end;
end;

end.
Yalnızım ama bir kente yürüyen ordu gibiyim, edebiyattan kaçınmalıyım..
Cevapla
#2
Firemonkey'in kendi Animation nesnelerini kullanırsan onlar paralel çalışabiliyor.

Circle nesnesi oluşturup bunun içine iki adet FloatAnimasyon koyup bunları X ve Y değerlerine bağlayabilirsin.

Böylece istediğin kadar top hareket ettirebilirsin.

X eksenindeki Lineer olacak, fakat Y ekseninde ivme olduğu için farklı bir çözüm bulman lazım.
Firemonkey çıkmadan önceki DxScene'de float animasyonların değerlerine müdahale edebiliyorduk diye hatırlıyorum ama tam emin değilim.

Diğer yandan internette Firemonkey için fizik motoru örneklerini de bulabilirsin.
Cevapla
#3
(16-08-2018, Saat: 19:41)ssahinoglu Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Firemonkey'in kendi Animation nesnelerini kullanırsan onlar paralel çalışabiliyor.

Circle nesnesi oluşturup bunun içine iki adet FloatAnimasyon koyup bunları X ve Y değerlerine bağlayabilirsin.

Böylece istediğin kadar top hareket ettirebilirsin.

X eksenindeki Lineer olacak, fakat Y ekseninde ivme olduğu için farklı bir çözüm bulman lazım.
Firemonkey çıkmadan önceki DxScene'de float animasyonların değerlerine müdahale edebiliyorduk diye hatırlıyorum ama tam emin değilim.

Diğer yandan internette Firemonkey için fizik motoru örneklerini de bulabilirsin.

Teşekkürler Fizik Motoru olayını araştıracağım. Benim animationlarda gördüğüm duration süre propertysi var ve ona göre verdiğin hedefe gidiyor ki orada da süreyi hesaplıyamadım. Şöyle bir şey denedim x eksenine animation ekleyip x'in ilerleyişinde y değerini değiştirdim ondada ivmeyi falan yakalıyamadım

Samples\Object Pascal\Multi-Device Samples\Physics\TestBed
burada embercaderonun kendi örnekleri var aslında ama kod bana çok karışık geldi
Yalnızım ama bir kente yürüyen ordu gibiyim, edebiyattan kaçınmalıyım..
Cevapla
#4
İvme kısmına kadar geldiysen ivme de interpolasyon yoluyla çözülür diye düşünüyorum.

Matlab veya Unity'de LERP gibi fonksiyonlar var. Bunların benzeri olabilir.
Zaten sen bu kodları yazabildiğine göre lineer olmayan bir interpolasyon fonksiyonu da yazabilirsin.

function DikeyInterpolasyon(BaslangicY:double; Hiz,Ivme:double; Sure:double):double;
Cevapla
#5
Merhaba,
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. ve Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. ile rahatlıkla istediğiniz ivme veya karışık bir rota belirleyebilirsiniz.
While true do; Hayat döngüsü, kısır değildir! Yapılan bir yanlış, o döngünün dışına çıkmanızı sağlayacaktır.
WWW
Cevapla
#6
(16-08-2018, Saat: 20:58)Fesih ARSLAN Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Merhaba,
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. ve Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. ile rahatlıkla istediğiniz ivme veya karışık bir rota belirleyebilirsiniz.

Deneyeceğim
Yalnızım ama bir kente yürüyen ordu gibiyim, edebiyattan kaçınmalıyım..
Cevapla




Konuyu Okuyanlar: 1 Ziyaretçi