Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - [VisualCLX] Gleichförmig 'verzögerte' beschleunigte Bewegung


ConditionZero - So 30.12.07 13:30
Titel: Gleichförmig 'verzögerte' beschleunigte Bewegung
Moin,

Also folgendes: Ich möchte ein Shape per Knopfdruck gleichförmig beschleunigt bewegen. Jedoch soll Beschleunigung a wie bei einem Auto immer niedriger werden, so das immer langsamer Beschleunigt wird. (siehe Grafik im Anhang)

Hier meine ersten Versuche:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if Key = VK_RETURN then
  begin
  a:= a+1;
  Shape1.Left:= Shape1.Left+a;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
a:= 1;
end;


Da passiert eigemtlich genau das was soll nur falsch herum...

Kann mir da jemand weiterhelfen?

Lg
Marc


Martok - So 30.12.07 13:34

Gleichförmig beschleunigt....autsch. Das heißt gleichmäßig beschleunigt ;)

Wenn a kleiner werden soll, warum addierst du dann 1? Einfach auf 10-20 initialisieren, und immer a-1 bis man bei 1 bzw 0 angekommen ist.


Mitmischer 1703 - So 30.12.07 13:35
Titel: Re: Gleichförmig 'verzögerte' beschleunigte Bewegung
user profile iconConditionZero hat folgendes geschrieben:


[delphi]
a:= a+1;
Shape1.Left:= Shape1.Left+a;


Da addierst du! Weiß nicht, ob das richtig ist :nixweiss:

EDIT: Zu langsam :autsch:


ConditionZero - So 30.12.07 13:48

user profile iconMartok hat folgendes geschrieben:
Gleichförmig beschleunigt....autsch. Das heißt gleichmäßig beschleunigt ;)


Mein Phsyikbuch sagt da aber was anderes... Also IMHO heißts Gleichfömig beschleunigte Bewegung :roll:



user profile iconMartok hat folgendes geschrieben:
Wenn a kleiner werden soll, warum addierst du dann 1? Einfach auf 10-20 initialisieren, und immer a-1 bis man bei 1 bzw 0 angekommen ist.


Ja genau da liegt aber das Problem... Anfangs habe ich dann eine extrem schnelle Bewegung und später eine kleinere.

Aber ein Auto wird ja immer schneller nicht immer langsamer...
d.h.: v muss antiproportional zu a steigen denn ein Auto ist wird ja auch immer schneller, nur der FAKTOR der Beschleungigung (zur Erinnerung [a]= Km/h²) muss sinken.


lg
marc


Martok - So 30.12.07 14:43

Gleichförmig ist doch gleichförmig und nicht beschleunigt... Jedenfalls bei uns.

Achso... dein a ist also v... oder was?
Naja, dann halt noch ne Variable, alles auf Float-Berechnungen umstellen und dann müsste es gehen.


ConditionZero - So 30.12.07 14:53

user profile iconMartok hat folgendes geschrieben:
Gleichförmig ist doch gleichförmig und nicht beschleunigt... Jedenfalls bei uns.


Das gleichförmig ist aber auf beschleunigte Bezogen, denn die Beschleunigung a steigt mit einem konstanten Faktor an ;)
Sonst würde es nämlich Gleichförmige, beschleunigte Bewegung heißen.



user profile iconMartok hat folgendes geschrieben:
Achso... dein a ist also v... oder was?
Naja, dann halt noch ne Variable, alles auf Float-Berechnungen umstellen und dann müsste es gehen.


Nein v existiert aus dem Grund noch nicht, da ich keine Ahnung habe wie ich den Wert von v berechnen kann. (Mit der Proportion von a)

lg
marc


GTA-Place - So 30.12.07 14:58

Öm... v = at?


ConditionZero - So 30.12.07 15:05

Ah genau... Thx
Also mit v = 0.5at² müsstes gehen (zum nachlesen ;))

Fraglich ist jetzt nur noch warum der Compiler FloatToInt(a); nicht erkennt.


lg
marc


Herr Bananerama - So 30.12.07 15:29

Seit ihr euch sicher das das eine konstante Beschleunigung ist und ne geradlinige Bewegung weil wir haben gelernt das diese in einem v t diagramm keine parabel sonder eine gerade mit a <> 0 ist !!!?


ConditionZero - So 30.12.07 15:35

Deswegen habe ich das Wörtchen verzögerte ins Topic mit rein... Das macht nämlich die ganze Sache erst kompliziert.
Die Beschleundigung a wird nämlich gleichförmig reduziert mit Konstanten Faktor (was nicht bedeutet Konstante Summe!)
Deshalb die Parabel.
Gehört glaube aber nicht zum normalen Unterrichtsstoff, wir haben das nämlich auch nicht auf diese Variante durchgenomme (Antiproportional anstatt proportional)

lg
marc


//Die Frage wegen dem Umkonvertieren steht noch :)


Herr Bananerama - So 30.12.07 15:54

user profile iconConditionZero hat folgendes geschrieben:
Ah genau... Thx
Also mit v = 0.5at² müsstes gehen (zum nachlesen ;))

Fraglich ist jetzt nur noch warum der Compiler FloatToInt(a); nicht erkennt.


lg
marc


ganz einfach ... es gibt kein FloatToInt. Eine gleitkommazahl in eine ganzzahl umwandeln tust du indem du rundest oder die stellen hinterm komma abschneidest. Das geht mit Round() und Trunc().


ConditionZero - So 30.12.07 16:06

Ok funkt. thx

Aber irgendwie Bewegt sich das Shape fürn Auto recht seltsam. (Anhang).

Hier aktueller Code:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
var
  Form1: TForm1;
  a,v: Real;
  t,vn: Integer;

implementation

{$R *.dfm}

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if Key = VK_RETURN then
  begin
  a:= a-0.3;
  v:=  0.5 * a * (t*t);
  vn:= Round(v)-Round(a);
  Shape1.Left:= Shape1.Left+vn;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
t:= 0;
a:= 15;
v:= 0;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
t:= t+1;
end;


lg
marc


//Sehr seltsam ist das sich das Shape immer anderst bewegt. lol


GTA-Place - So 30.12.07 16:14

user profile iconConditionZero hat folgendes geschrieben:
Also mit v = 0.5at² müsstes gehen

Nein, das wäre s = 1/2at² ;-)


ConditionZero - So 30.12.07 16:21

user profile iconGTA-Place hat folgendes geschrieben:
user profile iconConditionZero hat folgendes geschrieben:
Also mit v = 0.5at² müsstes gehen

Nein, das wäre s = 1/2at² ;-)


Recht haste... Ändert aber nichts groß am Bug.
Ich vermute schwer es liegt an dem a:= a-0.3;


lg
marc

//Edit: Die verschiedenen Bewegungen lagen am Timer, hatte vergesen Enabled auf false zu stellen.


Herr Bananerama - So 30.12.07 16:26

user profile iconConditionZero hat folgendes geschrieben:
user profile iconGTA-Place hat folgendes geschrieben:
user profile iconConditionZero hat folgendes geschrieben:
Also mit v = 0.5at² müsstes gehen

Nein, das wäre s = 1/2at² ;-)


Recht haste... Ändert aber nichts groß am Bug.
Ich vermute schwer es liegt an dem a:= a-0.3;


lg
marc

//Edit: Die verschiedenen Bewegungen lagen am Timer, hatte vergesen Enabled auf false zu stellen.


Dann muss a aber auch von anfang an eine negative beschleunigung sein, also einen negativen wert haben sonst ergibt das keinen Sinn


ConditionZero - So 30.12.07 16:28

Ich weiß zwar nicht warum, aber du hast Recht funzt schon vieel besser :) thx ich näher mich meinem Ziel *freu*

lg
marc


Herr Bananerama - So 30.12.07 16:59

user profile iconConditionZero hat folgendes geschrieben:
Ich weiß zwar nicht warum, aber du hast Recht funzt schon vieel besser :) thx ich näher mich meinem Ziel *freu*

lg
marc


Das ganze nennt man negative Beschleunigung und tritt z.B. auf wenn man bremst. Die beschleunigung ist negativ wenn
a < 0. Das sieht man im Graphen daran das er fällt.


ConditionZero - So 30.12.07 17:28

Ok, ich habe gerade bemerkt wir reden ein bisschen aneinander vorbei...

Also nochmal was ich erreichen will: Das Shape soll sich Verhalten wie ein Auto wenn es ohne weiteres von 0 auf Maximalgeschwindigkeit beschleunigt.

Das das KEINE gleichförmig beschleunigte Bewegung ist, erkennt man an folgender Veranschaulichung:

Wenn ein Auto 20 Km/h fährt, ist es zwar langsamer als wenn es 100 Km/h fährt, ABER die Beschleunigung a vom Auto ist noch besser als mit 100 Km/h. d.h. Je schneller das Auto fährt desto schlechter wird die Beschleunigung des Autos aber die eigentliche Geschwindigkeit ist trozdem höher... (Vielleicht macht die Tabelle im Anhang es leichter verständlich).

Und momentan ist der Fall:

Das Auto ist... Ehrlich gesagt keine Ahnung was grade schiefgeht, deswegen male ich nochmal ein Diagramm was den Fehler momentan veranschaulicht.


Herr Bananerama - So 30.12.07 17:37

user profile iconConditionZero hat folgendes geschrieben:
Ok, ich habe gerade bemerkt wir reden ein bisschen aneinander vorbei...

Also nochmal was ich erreichen will: Das Shape soll sich Verhalten wie ein Auto wenn es ohne weiteres von 0 auf Maximalgeschwindigkeit beschleunigt.

Das das KEINE gleichförmig beschleunigte Bewegung ist, erkennt man an folgender Veranschaulichung:

Wenn ein Auto 20 Km/h fährt, ist es zwar langsamer als wenn es 100 Km/h fährt, ABER die Beschleunigung a vom Auto ist noch besser als mit 100 Km/h. d.h. Je schneller das Auto fährt desto schlechter wird die Beschleunigung des Autos aber die eigentliche Geschwindigkeit ist trozdem höher... (Vielleicht macht die Tabelle im Anhang es leichter verständlich).

Und momentan ist der Fall:

Das Auto ist... Ehrlich gesagt keine Ahnung was grade schiefgeht, deswegen male ich nochmal ein Diagramm was den Fehler momentan veranschaulicht.



Ahh jetzt verstehe ich, hmmm dann gib uns doch nochmal die prozedur so wie du sie jetzt hast, vielleicht können wir dann ja irgendwas erkennen. Eigentlich ist dann was die anderen geschrieben haben aufjedenfall richtig würde ich sagen


ConditionZero - So 30.12.07 17:49

user profile iconHerr Bananerama hat folgendes geschrieben:
Ahh jetzt verstehe ich, hmmm dann gib uns doch nochmal die prozedur so wie du sie jetzt hast, vielleicht können wir dann ja irgendwas erkennen. Eigentlich ist dann was die anderen geschrieben haben aufjedenfall richtig würde ich sagen


Ok, hier nochmal der komplette Quellcode


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, XPMan;

type
  TForm1 = class(TForm)
    Shape1: TShape;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  a,v: Real;
  t: Integer;

implementation

{$R *.dfm}

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if Key = VK_RETURN then
  begin
  Timer1.Enabled:= true;
  v:= a*t;
  Shape1.Left:= Shape1.Left+Round(v)-Round(a);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
t:= 0;
a:= -15;
v:= 0;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
t:= t+1;
a:= a-0.3;
Timer1.Enabled:= false;
exit;
end;

end.


Herr Bananerama - So 30.12.07 18:05


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, XPMan;

type
  TForm1 = class(TForm)
    Shape1: TShape;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  a,v: Real;
  t: Integer;

implementation

{$R *.dfm}

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if Key = VK_RETURN then
  begin
  Timer1.Enabled:= true;
  v:= a*t;
  Shape1.Left:= Shape1.Left+Round(v); // wieso nochmal - a 
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
t:= 0;
a:= 15; // Das war doch falsch von mir wenn der nicht bremsen soll
v:= 0;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
t:= t+1;
a:= a-0.3;
Timer1.Enabled:= false;
exit; // Das hier ist unnötig, kannste streichen
end;

end.


DrRzf - So 30.12.07 18:58

Mal euren Source anguck :lupe:

Was bewirkt der Timer ? :gruebel:

der timer wird bei tastendruck gestartet und berechnet nach gewisser zeit die neue position und wird wieder gestoppt.
das shape wird aber sofort bei tastendruck bewegt.
die berechnung könnte man genausogut in die prcedure wo das shape verschoben wird setzen. (warum dafür nen timer quälen ?


ConditionZero - So 30.12.07 18:59

Weil der Timer t erhöhen muss, damit man v ausrechnen kann.

lg
marc


ConditionZero - So 30.12.07 19:01

Zitat:
Shape1.Left:= Shape1.Left+Round(v); // wieso nochmal - a

weiß ich ehrlich gesagt auch nicht mehr ^^



Zitat:
a:= 15; // Das war doch falsch von mir wenn der nicht bremsen soll

Achso okl.


Zitat:
exit; // Das hier ist unnötig, kannste streichen


Jo, da hatte ich was auprobiert.

lg
marc


DrRzf - So 30.12.07 19:03

was nützts wenn dus aber nicht anzeigst ?
du stoppst den Timer wieder, also führt er nur eine berechnung durch, da kann ichs gleich beim tastendruck machen :think:
Wenn dann im OnKeyDown den Timer bei VK_Left starten.
In der Timerprocedure jedesmal neue Position berechnen und das Shape schieben.
Wenn beschleunigung <= 0 dann den Timer wieder stoppen.


ConditionZero - So 30.12.07 19:14

Ja klaro er erhöht die Zeit, damit die Formel in OnKeyDown (v:= a*t;) wieder stimmt und dann wird im OnKeyDown die Ausgabe gemacht... Weiß jetzt nicht so genau was du meinst. Sorry.


lg
marc

// Und wieso VK_Left???


DrRzf - So 30.12.07 19:39

irgendwie iss das nicht logisch....

im OnKeyDown wird der Timer gestartet damit die neue Position nach xxxms neu berechnet wird.
aber das shape wird bei OnKeyDown neu gezeichnet.

wie soll das funzen ?
ich drück die taste, das shape bewegt sich nicht, da immer noch selbe position.
nach ner gewissen zeit wird die position berehcnet, dann drück ich left und da shape bewegt sich um eine position weiter.

VK_LEFT
meinte eigentlich VK_RETURN ^^


Edit
habs grad mal angetestet.
das shape bewegt sich zuerst kurz bei festhalten der taste, dann wirds schneller, und fetzt dann über den rand raus.
hängt damit zusammen, dass die OnKeyPress immer wieder aufgerufen wird, daher ist der timer für die katz so wie er eingesetzt wird.


ConditionZero - So 30.12.07 19:57

Stimmt, aber ich habe so ziemlich den Faden verloren, wie du es meinst.
Paar Posts vornedran hab ich mal noch geschrieben, wie sich das Shape bewegen soll.

Paar Zeilen Code von dir wie du es machen würdest, könnten mir sicher erheblich weiterhelfen :)

lg
marc


DrRzf - So 30.12.07 20:00

ich baus dir um, tu mir zuerst aber noch einen lukullisches mahl einnehmen :puke:


ConditionZero - So 30.12.07 20:40

Ok, bin schon gespannt :)


LG
Marc


DrRzf - So 30.12.07 21:25

hab da mal was gebastelt.
linkes edit = intervall timer
mittleres edit = beschleunigungmultiplikator
rechtes edit = beschleunigungsfaktor (100 = linear; >100 beschleunigungszuwachs nimmt zu, <100 beschleunihgungsf nimmt ab)

Starten kannste das ganze mit dem StartButton ^^


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
var
  Form1: TForm1;
  b,a,v,e: Real;

implementation

{$R *.dfm}

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  a := a + b;
  v := Power(a,e);
  Shape1.Left:= Shape1.Left+Round(v);
  if (Shape1.Left + Shape1.Width) > Form1.Width then ButtonStartPosClick(Self);
  Label3.Caption := FloatToStrf(v,ffFixed,10,2);
  Form1.Repaint;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ButtonStartPosClick(Self);
end;

procedure TForm1.ButtonStartPosClick(Sender: TObject);
begin
  Timer1.Enabled := false;
  Shape1.Left := 5;
  Timer1.Interval := StrToInt(Edit1.Text);
  b := StrToInt(Edit2.Text) / 1000;
  e := StrToInt(Edit3.Text) / 100;
  a := 0;
  v := 0;
end;

procedure TForm1.ButtonStartClick(Sender: TObject);
begin
  ButtonStartPosClick(Self);
  if Timer1.Enabled then Timer1.Enabled := false
    else Timer1.Enabled := true;
end;


ConditionZero - So 30.12.07 21:32

Wow, danke :)

Jetzt versteh ich auch was du meintest mit dem Timer...
Ok damit ist das Problem gelöst.

Thanks@all

LG
Marc