Entwickler-Ecke
Algorithmen, Optimierung und Assembler - Bewegung sanft abbremsen
Passi077 - Do 25.08.05 12:43
Titel: Bewegung sanft abbremsen
Hi,
ich Berechne in einer MainLoop Schleife eine Bewegung durch folgende Vorgehensweise:
Gegeben: Start- und Endpunkt, z.B. (100|200) sowie die aktuelle Position, z.B. 134
Berechnung der Bewegung: (Position (134) - X (100)) / (Y - X)
Das Funktioniert auch wunderbar, dann bekomme ich bei Position 100 eine 0, und bei Position 200 eine 1.
Nun würde ich gerne diese Bewegung am Ende Abbremsen. Das Problem an der Sache ist, dass trotz der Abbremsung die Bewegung am Endpunkt (hier 200) auf jeden Fall 1 betragen muss. D.h. es muss wohl erst auch noch errechnet werden, wann mit dem Abbremsen begonnen werden muss.
Leider steht ich da etwas auf dem Schlauch. Habe rumprobiert mit Zerfallsfunktionen, aber ich komme zu keinem aktzeptablen Ergebnis. Hab ihr eine Idee, wie ich das lösen kann?
Desweiteren noch die Anmerkung: Da die Position sprunghaft geändert werden kann, wird alles direkt auf die Position bezogen berechnet - also nichts mit Status := Status + 5 oder ähnlich ;).
Danke + Grüße
Passi
delfiphan - Do 25.08.05 14:10
Passi077 hat folgendes geschrieben: |
Berechnung der Bewegung: (Position (134) - X (100)) / (Y - X) |
Ich sehe ein, dass die Funktion linear zwischen 0 und 1 variiert, wenn das Argument (Position) zwischen X und Y variiert. Was das genau mit einer Bewegung zu tun hat, seh ich nicht ein. Könntest du also bitte etwas genauer definieren, was du mit der berechneten Zahl zwischen 0 und 1 überhaupt machst, und woraus du dann die Geschwindigkeit berechnest? Was ist konkret vorgegeben und was willst du am Schluss genau haben (Positionen, Geschwindigkeiten, ?)
Passi077 hat folgendes geschrieben: |
Da die Position sprunghaft geändert werden kann, wird alles direkt auf die Position bezogen berechnet - also nichts mit Status := Status + 5 oder ähnlich |
Was ist die Position und was meinst du, dass alles direkt auf die Position bezogen berechnet wird. Sehe ich das richtig, dass du einen Anfangs- und Endpunkt sowie eine "aktuelle Position" eines Objektes hast; und dass du aus dieser "aktuellen Position" die neue Position im nächsten Zeitschritt berechnen willst?
Auf welche Art soll die Geschwindigkeit abnehmen? (Sprunghafte Abnahme wenn genug nahe am Endpunkt, lineare Abnahme, glatte Abnahme (halber Cosinus oder sowas), exponentiell?)
Vielleicht hilft's wenn du noch sagst, wofür du das ganze brauchst.
Passi077 - Do 25.08.05 15:10
Wenn ich die Zahl berechnet habe, errechne ich z.B. eine Rotation daraus:
Quelltext
1:
| Draw(X, Y, 360*Faktor); |
-> Faktor zwischen 0 und 1 -> Das gezeichnete dreht sich einmal um die eigene Achse.
Was die Position angeht: Das Ganze kann man sich wie einen VideoPlayer vorstellen. Die Position gibt die aktuelle Zeit an und wir konstant erhöht. Ist das geschehen, rufe ich eine Prozedur auf, die dann resultierend aus der aktuellen Position das entsprechende Bild errechnet.
Ich errechne und benötige also keine Geschwindigkeiten, diese ergeben sich automatisch aus dem vorgegebenen Start- und Endpunkt der Animation.
Zur Verdeutlichung:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| While 5 > 3 do begin Position := Position + 1; Start := 50; Ende := 100; Draw_Animation(Position);
end;
procedure Draw_Animation(position: integer); begin if (position >= 50) and (position <= 100) then begin Faktor := (position - Start) / (Ende - Start); Draw(X, Y, 360*Faktor); end; end; |
Und da möchte ich nun die besagte Abbremsung einbauen. Wie das abgebremst wird, eigentlich keine Ahnung weil ich mir das alles nicht so recht vorstellen kann, aber ich glaub eine viertel Periode des Sinus sieht ganz gut aus.
delfiphan - Do 25.08.05 22:41
Sowas vielleicht:
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:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls;
type TForm1 = class(TForm) Shape1: TShape; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private public Start, Ende, Pos: Single; function GeschwFunk(x: Single): Single; end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject); begin Start := 0; Ende := 100; Pos := 0; end;
function TForm1.GeschwFunk(x: Single): Single; const GeschwMax = 200; begin Result := cos(x*pi/2)*GeschwMax; end;
procedure TForm1.Timer1Timer(Sender: TObject); var dt: Single; begin dt := Timer1.Interval / 1000; Pos := Pos + dt*GeschwFunk((Pos - Start)/(Ende - Start)); Shape1.Left := Round(Pos); end;
end. |
Hier noch die DFM-Datei (Bei der Formansicht Alt+F12 drücken und reinkopieren, dann wieder Alt+F12):
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:
| object Form1: TForm1 Left = 192 Top = 114 Width = 571 Height = 406 Caption = 'Form1' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 object Shape1: TShape Left = 16 Top = 56 Width = 65 Height = 65 end object Timer1: TTimer Interval = 10 OnTimer = Timer1Timer Left = 16 Top = 16 end end |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!