Sanfte Animation eines Panels von links nach rechts
-
- Beiträge: 1
- Registriert: Do 17. Okt 2024, 12:40
Sanfte Animation eines Panels von links nach rechts
Hallo,
ich möchte das sich z.B. ein Panel waagerecht vom linken Bildschirmrand zum rechten
Bildschirmrand hin- und herbewegt.
Das bekomme ich ohne Probleme hin- das Panel soll aber weich abbremsen und beschleunigen...
Es geht mir um das generelle Konzept. Wie programmiert man so etwas.
Bin für jeden Hinweis dankbar.
ich möchte das sich z.B. ein Panel waagerecht vom linken Bildschirmrand zum rechten
Bildschirmrand hin- und herbewegt.
Das bekomme ich ohne Probleme hin- das Panel soll aber weich abbremsen und beschleunigen...
Es geht mir um das generelle Konzept. Wie programmiert man so etwas.
Bin für jeden Hinweis dankbar.
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Sanfte Animation eines Panels von links nach rechts
Wie im Physikunterricht:
Geschwindigkeit = Beschleunigung*Zeit
Position = Geschwindigkeit*Zeit=Bescheunligung*Zeit*Zeit
Du suchst dir also aus mit welcher maximalgeschwindigkeit das Panel sich bewegen soll, z.B. 100 pixel pro sekunde, und eine Beschleunigung, z.B. 20pixel pro sekunde pro sekunde. Dann berechnest du wie lang der beschleunigungs und bremszeit ist, 100/20=5 sekunden. Dann berechest du wie lang der Bremsweg ist, 20*5^2 = 500 pixel.
D.h. du fängst an zu beschleunigen mit 20 pixeln pro sekunde bis du 100 pixel pro sekunde erreichst, dabei ist dein Panel bereits schon 500 pixel geandert. Sobald du 500 pixel vor dem Ende bist bremst du ab mit -20 pixel pro sekunde pro Sekunde.
Viel einfacher ists wenn dir die Maximalgeschwindigkeit egal ist, denn dann kannst du einfach flat ab der hälfte abbremsen, weil die Beschleunigungszeit natürlich immer Equivalent zur Bremszeit ist.
Beispiel (bewegt Button1 abwechseld von links nach rechts und von rechts nach links):
Geschwindigkeit = Beschleunigung*Zeit
Position = Geschwindigkeit*Zeit=Bescheunligung*Zeit*Zeit
Du suchst dir also aus mit welcher maximalgeschwindigkeit das Panel sich bewegen soll, z.B. 100 pixel pro sekunde, und eine Beschleunigung, z.B. 20pixel pro sekunde pro sekunde. Dann berechnest du wie lang der beschleunigungs und bremszeit ist, 100/20=5 sekunden. Dann berechest du wie lang der Bremsweg ist, 20*5^2 = 500 pixel.
D.h. du fängst an zu beschleunigen mit 20 pixeln pro sekunde bis du 100 pixel pro sekunde erreichst, dabei ist dein Panel bereits schon 500 pixel geandert. Sobald du 500 pixel vor dem Ende bist bremst du ab mit -20 pixel pro sekunde pro Sekunde.
Viel einfacher ists wenn dir die Maximalgeschwindigkeit egal ist, denn dann kannst du einfach flat ab der hälfte abbremsen, weil die Beschleunigungszeit natürlich immer Equivalent zur Bremszeit ist.
Beispiel (bewegt Button1 abwechseld von links nach rechts und von rechts nach links):
Code: Alles auswählen
procedure TForm1.Timer1Timer(Sender:TObject);
const
MaxSpeed = 100;
Acceleration = 20;
Breakpoint = Acceleration*(MaxSpeed/Acceleration)*(MaxSpeed/Acceleration);
const
CurrentSpeed: Double = 0;
LastTime: QWord = 0;
var
TimeDiff:Double;
begin
if LastTime = 0 then
begin
LastTime:=GetTickCount64;
Exit;
end;
TimeDiff:=(GetTickCount64-LastTime)/1000;
LastTime:=GetTickCount64;
if (Button1.Left+Button1.Width/2<ClientWidth/2) and (
(CurrentSpeed<>MaxSpeed) or
(Button1.Left+Button1.Width/2<ClientWidth-BreakPoint)
) and (
(CurrentSpeed<>-MaxSpeed) or
(Button1.Left+Button1.Width/2>BreakPoint)
) then
CurrentSpeed:=Min(CurrentSpeed+Acceleration*TimeDiff, MaxSpeed)
else
CurrentSpeed:=Max(CurrentSpeed-Acceleration*TimeDiff, -MaxSpeed);
Form1.Caption:=CurrentSpeed.ToString;
Button1.Left:=Round(Button1.Left + CurrentSpeed);
end;
Zuletzt geändert von Warf am Do 17. Okt 2024, 22:32, insgesamt 1-mal geändert.
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Sanfte Animation eines Panels von links nach rechts
Ich mache sowas in dieser Art.
Code: Alles auswählen
procedure TForm1.Timer1Timer(Sender: TObject);
const
c:Single=0;
begin
Button1.Left:=round((sin(c)+1)*100);
c+=0.1;
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 1061
- Registriert: Sa 12. Sep 2015, 12:10
- OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
- CPU-Target: Win 32/64, Linux64
- Wohnort: Wien
Re: Sanfte Animation eines Panels von links nach rechts
ahem -- hab da fachlich nix dazu zu sagen, bloss eine Frage:
Meines Wissens kann man eine Konstante nicht inkrementieren.
Liege ich da falsch?
Meines Wissens kann man eine Konstante nicht inkrementieren.
Liege ich da falsch?
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1639
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Sanfte Animation eines Panels von links nach rechts
Das ist keine echte Konstante. Nur eine initialisierte Variable.charlytango hat geschrieben: Do 17. Okt 2024, 23:24 ahem -- hab da fachlich nix dazu zu sagen, bloss eine Frage:
Meines Wissens kann man eine Konstante nicht inkrementieren.
Liege ich da falsch?
Code: Alles auswählen
const c = 0.1;
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1639
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Sanfte Animation eines Panels von links nach rechts
Wenn man statt der Konstanten 100Mathias hat geschrieben: Do 17. Okt 2024, 21:28 Ich mache sowas in dieser Art.Code: Alles auswählen
procedure TForm1.Timer1Timer(Sender: TObject); const c:Single=0; begin Button1.Left:=round((sin(c)+1)*100); c+=0.1; end;
Code: Alles auswählen
Button1.Left:=round((sin(c)+1)*((width-Button1.Width) shr 1));
- Niesi
- Lazarusforum e. V.
- Beiträge: 587
- Registriert: So 26. Jun 2016, 19:44
- OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 4.1 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
- Kontaktdaten:
Re: Sanfte Animation eines Panels von links nach rechts
fliegermichl hat geschrieben: Fr 18. Okt 2024, 08:34Das ist keine echte Konstante. Nur eine initialisierte Variable.charlytango hat geschrieben: Do 17. Okt 2024, 23:24 ahem -- hab da fachlich nix dazu zu sagen, bloss eine Frage:
Meines Wissens kann man eine Konstante nicht inkrementieren.
Liege ich da falsch?Die ist unveränderlich.Code: Alles auswählen
const c = 0.1;
Niklaus Wirth drehte sich im Grab um - eine Konstante, die eine initialisierte Variable ist.

Sein Motto war immer: Programmieren muss einfach sein ...



https://www.golem.de/news/nachruf-infor ... 80806.html
https://de.wikipedia.org/wiki/Wirthsches_Gesetz
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Sanfte Animation eines Panels von links nach rechts
Eine typisierte Konstante ist in der Standard Einstellung eine "Writable Const". Das heißt es ist keine Konstante sondern eine Variable mit statischer Lebenszeit. In anderen Sprachen nennt sich das "static variable".
Im Grunde was es bedeutet, es ist eine Variable die nur für die Funktion zugänglich ist, aber über Funktionsaufrufe hinweg bestelt. Also eine globale Variable mit lokaler Sichtbarkeit. Beispiel:
Diese funktion gibt in jedem Aufruf den wert des Vorrigen Aufrufs + 1 zurück.
Sowas kann sehr nützlich sein in einigen Fällen. in meinem Beispiel oben hab ich es einfach benutzt damit ich alles in einer Schönen funktion hab, was es einfacher macht das ganze hier im Forum zu teilen.
Für diesen Fall ist das natürlich aber eher Suboptimal, denn die Variablen sind auch über verschiedene Instanzen der selben Klasse geteilt, d.h. wenn man mehr als eine Instanz dieser Form hat, würden die sich gegenseitig zwischen funken. Daher sollte für eine Umsetzung das als Feld in die Klasse gebracht werden.
Gibt aber dennoch mehr als genug Fälle in denen das eine super Lösung ist, und da das Hauptproblem von Globalen Variablen der Globale Scope ist, ist es normalerweise Ratsam wenn man eine Globale Variable nur innerhalb einer Funktion (und ggf einigen Helferfunktionen) braucht, diese als Writeable Const lokal zu definieren.
Das die Syntax absolut Grauenvoll ist mit dem "const" keyword stimm ich voll und ganz zu. Dennoch ein sehr nützliches Konzept
Im Grunde was es bedeutet, es ist eine Variable die nur für die Funktion zugänglich ist, aber über Funktionsaufrufe hinweg bestelt. Also eine globale Variable mit lokaler Sichtbarkeit. Beispiel:
Code: Alles auswählen
function NextIndex: Integer;
const
Counter: Integer=0;
begin
Result:=Counter;
Inc(Counter);
end;
Sowas kann sehr nützlich sein in einigen Fällen. in meinem Beispiel oben hab ich es einfach benutzt damit ich alles in einer Schönen funktion hab, was es einfacher macht das ganze hier im Forum zu teilen.
Für diesen Fall ist das natürlich aber eher Suboptimal, denn die Variablen sind auch über verschiedene Instanzen der selben Klasse geteilt, d.h. wenn man mehr als eine Instanz dieser Form hat, würden die sich gegenseitig zwischen funken. Daher sollte für eine Umsetzung das als Feld in die Klasse gebracht werden.
Gibt aber dennoch mehr als genug Fälle in denen das eine super Lösung ist, und da das Hauptproblem von Globalen Variablen der Globale Scope ist, ist es normalerweise Ratsam wenn man eine Globale Variable nur innerhalb einer Funktion (und ggf einigen Helferfunktionen) braucht, diese als Writeable Const lokal zu definieren.
Das die Syntax absolut Grauenvoll ist mit dem "const" keyword stimm ich voll und ganz zu. Dennoch ein sehr nützliches Konzept
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Sanfte Animation eines Panels von links nach rechts
Ja das ist die andere Methode, man kann sich eine Funktion ausdenken die den Weg beschreibt, z.B. Sinus oder Parabolisch, und dann die Position auf dieser Kurve ausrechnen und auf die Horizontalachse abbilden.Mathias hat geschrieben: Do 17. Okt 2024, 21:28 Ich mache sowas in dieser Art.Code: Alles auswählen
procedure TForm1.Timer1Timer(Sender: TObject); const c:Single=0; begin Button1.Left:=round((sin(c)+1)*100); c+=0.1; end;
Was man allerdings noch beachten sollte ist das je nach Auslastung Timer nicht uniform ticken, d.h. man sollte lieber die Zeitschritte nach der Tatsächlich vergangenen Zeit normalisieren:
Code: Alles auswählen
procedure TForm1.Timer1Timer(Sender: TObject);
const
curveSpeed=10;
const
c:Single=0;
LastTime:QWord=0;
var
TimeDelta:Double;
begin
if LastTime=0 then
TimeDelta:=0
else
TimeDelta:=(GetTickCount64-LastTime)/1000;
LastTime:=GetTickCount64;
Button1.Left:=round((sin(c)+1)*100);
c+=CurveSpeed*TimeDelta;
end;
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Sanfte Animation eines Panels von links nach rechts
Dies ist in meinen Augen nicht sauber gelöst, eine Konstante dürfte wie der Name schon sagt, nicht änderbar sein.Das die Syntax absolut Grauenvoll ist mit dem "const" keyword stimm ich voll und ganz zu. Dennoch ein sehr nützliches Konzept
So wäre es viel sauberer gelöst.
Code: Alles auswählen
var
counter: integer = 0; static;
Dies ist mir bewusst, dies sollte man bei jeder Animation machen, vor allem wen das ganze über die Framerate gesteuert ist.Was man allerdings noch beachten sollte ist das je nach Auslastung Timer nicht uniform ticken, d.h. man sollte lieber die Zeitschritte nach der Tatsächlich vergangenen Zeit normalisieren:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Sanfte Animation eines Panels von links nach rechts
Das ist eine der Sachen die finde ich haben Modernere UI Frameworks wie WPF oder Firemonkey besser gelöst, das es dort schon predefinierte Animationsframeworks gibt mit denen man sowas recht trivial wird
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Sanfte Animation eines Panels von links nach rechts
Mit HTML ist solches Zeugs auch möglich.Warf hat geschrieben: Fr 18. Okt 2024, 17:29 Das ist eine der Sachen die finde ich haben Modernere UI Frameworks wie WPF oder Firemonkey besser gelöst, das es dort schon predefinierte Animationsframeworks gibt mit denen man sowas recht trivial wird
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 954
- Registriert: Mi 3. Jun 2020, 07:18
- OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
- CPU-Target: Aarch64 bis Z80 ;)
- Wohnort: München
Re: Sanfte Animation eines Panels von links nach rechts
In diesem Kontext sollte man wohl auch die sogenannten „Easing Funktionen” erwähnen, welche im Zusammenhang mit Animationen häufig genutzt werden, um zwischen zwei Werten (zum Beispiel Positionen) zu interpolieren. Die verlinkte Webseite hat auch die mathematischen Funktionen, welche in FPC reimplementiert werden können.
FPC Compiler Entwickler
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1639
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Sanfte Animation eines Panels von links nach rechts
Ah ja, die hatte ich schonmal nach Pascal portiert. Muss ich mal raussuchen.PascalDragon hat geschrieben: So 20. Okt 2024, 11:32 In diesem Kontext sollte man wohl auch die sogenannten „Easing Funktionen” erwähnen, welche im Zusammenhang mit Animationen häufig genutzt werden, um zwischen zwei Werten (zum Beispiel Positionen) zu interpolieren. Die verlinkte Webseite hat auch die mathematischen Funktionen, welche in FPC reimplementiert werden können.