Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Kreisförmige Bewegung eines Objektes (https://www.delphipraxis.net/76961-kreisfoermige-bewegung-eines-objektes.html)

ErdNussLocke 12. Sep 2006 18:01


Kreisförmige Bewegung eines Objektes
 
Hi,
ich will, dass sich ein Objekt, am Besten ein Label, auf dem Forumlar im Kreis bewegt (es soll sich nicht drehen).
Hat wer eine Idee? Ich habs mit sin versucht, aber man kann ja nur mit Bogenmaß arbeiten -> keine Kommazahlen in label1.left
Danke im Vorraus
ErdNussLocke

Dax 12. Sep 2006 18:02

Re: Kreisförmige Bewegung eines Objektes
 
Beim zuweisen Rounden.

Nikolas 12. Sep 2006 18:14

Re: Kreisförmige Bewegung eines Objektes
 
Was ist mir Komma-Zahlen in deinem Label? Position einfach per (sin(x),cos(x)) festlegen und dann je nach Vorliebe noch die Funktionen degtorad/RadToDeg benutzen.

ErdNussLocke 12. Sep 2006 18:41

Re: Kreisförmige Bewegung eines Objektes
 
Aber wie lege ich denn die Position fest? Ich kenne nur label1.left:=X; Wenn ich da einen Kommawert eingebe kommt ein Fehler.

Cöster 12. Sep 2006 18:47

Re: Kreisförmige Bewegung eines Objektes
 
Zitat:

Zitat von ErdNussLocke
Aber wie lege ich denn die Position fest? Ich kenne nur label1.left:=X; Wenn ich da einen Kommawert eingebe kommt ein Fehler.

Label1.Left := Trunc(X);

Trunc rundet X, sodass Label1.Left ein Integer-Wert zugewiesen wird.

Falls du einen fertigen Code haben willst, sag Bescheid. Aber vll kriegst du's jetzt ja auch selber hin.

Nikolas 12. Sep 2006 18:48

Re: Kreisförmige Bewegung eines Objektes
 
Wo gibts du welchen Wert ein, das welcher Fehler kommt? Was willst du genau machen?

ErdNussLocke 12. Sep 2006 18:53

Re: Kreisförmige Bewegung eines Objektes
 
Krieg ich nicht hin :( Wenn ich z.B. sin(360) runde kommt ja eins raus, weil das ja noch knapp kleiner is als 1. Aber mit nur 2 Zahlen kann ich ja keine Kreisbewegung simulieren :-/

TStringlist 12. Sep 2006 18:59

Re: Kreisförmige Bewegung eines Objektes
 
event. geht es ja so:


Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  // Radius des Einheitskreises = 40 Dots
  X0 := Label1.left - 40;
  Y0 := Label1.top;
  Grad := 0;
  Timer1.Enabled := true
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  inc(Grad,2);
  Label1.left := X0 + round (cos(2*Pi/360 * Grad) * 40);
  Label1.Top := Y0 - round (sin(2*Pi/360 * Grad) * 40);
  if Grad = 360 then Timer1.Enabled := false
end;

benst 12. Sep 2006 19:09

Re: Kreisförmige Bewegung eines Objektes
 
@TStringlist: Jetzt war ich auch gerade fertig mit meinem Vorschlag, aber du warst schneller :)

Man kann noch den Radius und die Drehrichtung einbeziehen:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  XR := 40;
  YR := 40;
  X0 := Label1.left - XR;
  Y0 := Label1.top;
  Grad := 0;
  Richtung := 1 //1 = mathematische pos. Drehsinn (gegen Uhrzeigersinn), -1 = entsprechend anders herum
  Timer1.Enabled := true
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  inc(Grad,2);
  Label1.left := X0 + round (cos(2*Pi/360 * Grad) * XR);
  Label1.Top := Y0 - round (sin(2*Pi/360 * Richtung * Grad) * YR);
  if Grad = 360 then Timer1.Enabled := false
end;
... wenn man XR und YR unterschliedlich groß macht, entsteht eine Ellipse.

ErdNussLocke 12. Sep 2006 19:12

Re: Kreisförmige Bewegung eines Objektes
 
Danke sehr. Es funktionert! :)
Zwei Fragen noch:
Wozu steht die "2" bei "inc(Grad,2)"?
Warum bei der "left"+"top"- Zuweisung am Ende *40?
Thx

Waldteufel 12. Sep 2006 19:16

Re: Kreisförmige Bewegung eines Objektes
 
Hi ErdnussLocke.

Zitat:

Zitat von ErdNussLocke
Wozu steht die "2" bei "inc(Grad,2)"?

Inc(Grad) heißt: Erhöhe Grad (um 1).
Inc(Grad) heißt: Erhöhe Grad um 2.

Zitat:

Zitat von ErdNussLocke
Warum bei der "left"+"top"- Zuweisung am Ende *40?

Weil der Sinus nur zwischen 1 und -1 hin- und herschwingt. Das wäre ein ziemlich kleiner Kreis. Deshalb mal 40 (Radius).

Gruß,
Waldteufel

benst 12. Sep 2006 19:18

Re: Kreisförmige Bewegung eines Objektes
 
Für kontinuierliches Drehen:
Anstatt:
Inc(Grad, 2);
folgendes:
Grad:=(Grad+2) mod 360;
... und
if Grad = 360 then Timer1.Enabled := false
weglassen.
Also so:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  XR := 40;
  YR := 40;
  X0 := Label1.left - XR;
  Y0 := Label1.top;
  Grad := 0;
  Richtung := 1 //1 = mathematische pos. Drehsinn (gegen Uhrzeigersinn), -1 = entsprechend anders herum
  Timer1.Enabled := true
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Grad:=(Grad+2) mod 360;
  Label1.left := X0 + round (cos(2*Pi/360 * Grad) * XR);
  Label1.Top := Y0 - round (sin(2*Pi/360 * Richtung * Grad) * YR);
end;
(Für sehr große Kreise Grad:=(Grad+1)mod 360, falls es ruckelt.)

ErdNussLocke 12. Sep 2006 19:18

Re: Kreisförmige Bewegung eines Objektes
 
thx!
Dann hab ichs jetz verstanden!
Danke an euch alle!
Bis zum nächsten Prob ;)
MfG
ErdNussLocke

Nikolas 12. Sep 2006 19:28

Re: Kreisförmige Bewegung eines Objektes
 
Das mod ist aber völlig überflüssig. Die Sinusfunktion ist doch schön periodisch (sin(alpha)=sin(alpha+360°) oder sin(x)=sin(x+2 pi))

benst 12. Sep 2006 19:30

Re: Kreisförmige Bewegung eines Objektes
 
Das habe ich zuerst auch gedacht und das geht vermutlich auch gut. Sauber programmiert ist das aber (wie ich finde) nicht, weil es irgendwann zum Überlauf kommt.

QuickAndDirty 13. Sep 2006 13:56

Re: Kreisförmige Bewegung eines Objektes
 
Naja, "sauber" programmiert wäre es, alle x und y eines 1/4 Kreises zu speichern
und den Rest durch Spiegelung an der X- und/oder der Y-Achse zu ermitteln.
Das schont den Prozessor....Sin und Cos ist nicht mal eben so ermittelt.

himitsu 13. Sep 2006 14:18

Re: Kreisförmige Bewegung eines Objektes
 
Zitat:

Zitat von benst
Das habe ich zuerst auch gedacht und das geht vermutlich auch gut. Sauber programmiert ist das aber (wie ich finde) nicht, weil es irgendwann zum Überlauf kommt.

Wenn du jetzt statt der 360 eine schöne Zweierpotenz nutzt, am Besten sogar noch in einen Datentypen perfekt reinpassend (z.B. Byte=256, Word=65536, ... ), dann kannst du das "langsame" MOD auch weglassen und höchstens mit einem netten AND arbeiten :)

Delphi-Quellcode:
Var Grad: Byte; {0..255}

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Inc(Grad, 2);
  Label1.left := X0 + round (cos(Pi/128 * Grad) * XR);
  Label1.Top := Y0 - round (sin(Pi/128 * Richtung * Grad) * YR);
end;
oder halt mit belibigen Zweierpotenzen und AND:
Delphi-Quellcode:
Var Grad: Integer; {z.B.: 0..1023}

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Grad := (Grad + 2) and $03FF;
  Label1.left := X0 + round (cos(Pi/512 * Grad) * XR);
  Label1.Top := Y0 - round (sin(Pi/512 * Richtung * Grad) * YR);
end;

Novilos 13. Sep 2006 15:44

Re: Kreisförmige Bewegung eines Objektes
 
Zitat:

Zitat von TStringlist
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  // Radius des Einheitskreises = 40 Dots
  X0 := Label1.left - 40;
  Y0 := Label1.top;
  Grad := 0;
  Timer1.Enabled := true
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  inc(Grad,2);
  Label1.left := X0 + round (cos(2*Pi/360 * Grad) * 40);
  Label1.Top := Y0 - round (sin(2*Pi/360 * Grad) * 40);
  if Grad = 360 then Timer1.Enabled := false
end;

Kann mir wer die Rechnung erklären? Wie das mit Sin und Cos genau abläuft? Versteh ich nicht so ganz :)
Danke sehr

Nikolas 13. Sep 2006 15:55

Re: Kreisförmige Bewegung eines Objektes
 
naja, 2pi/360*Grad verwandelt Grad von Rad zu Deg, wie du Funktion RadtoDeg. also 0-360 -> 0-2pi. Die 40 ist der Radius des Kreises.
Wie sin und cos am Einheitskreis definiert sind, kannst du in der WIkipedia lesen.

himitsu 13. Sep 2006 15:58

Re: Kreisförmige Bewegung eines Objektes
 
Schau mal im Tafelwerk, bei Wikipedia, oder sonstwo nach Kreisfunktionen, als sowas schimpfen sich Sinus und Cosinus schließlich :zwinker:

Cöster 13. Sep 2006 15:59

Re: Kreisförmige Bewegung eines Objektes
 
Zitat:

Zitat von Novilos
Zitat:

Zitat von TStringlist
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  // Radius des Einheitskreises = 40 Dots
  X0 := Label1.left - 40;
  Y0 := Label1.top;
  Grad := 0;
  Timer1.Enabled := true
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  inc(Grad,2);
  Label1.left := X0 + round (cos(2*Pi/360 * Grad) * 40);
  Label1.Top := Y0 - round (sin(2*Pi/360 * Grad) * 40);
  if Grad = 360 then Timer1.Enabled := false
end;

Kann mir wer die Rechnung erklären? Wie das mit Sin und Cos genau abläuft? Versteh ich nicht so ganz :)
Danke sehr

Der Sinus eines Winkels ist Gegenkathete durch Hypothenuse. Die Hypothenuse ist der Radius des Umlaufkreises. Der ist in dem Beispiel 40. Sin(Winkel)*40 ist also die länge der Gegenkathete bei einem Winkel und dem Radius 40. Es berechnet, wie weit die Y-Position des Labels sich über dem Mittelpunkt des Kreise befindet. Ist der Sinus negativ, befindet sich das Label unterhalb des Mittelpunktes.
Cos ist Ankathete/Hypothenuse und berechnet das gleiche für die X-Position.
Die Winkel, von denen der Cosinus bzw. Sinus berechnet wird, müssen in Delphi immer in Bogenmaß statt in Grad sein. Deswegen 2*Pi/360*Grad. Das könnte man alternativ auch mit DegToRad(Grad) machen.

TStringlist 13. Sep 2006 16:46

Re: Kreisförmige Bewegung eines Objektes
 
Hier nochmal ein ganz trivialer Erklärungsversuch: Du kennst doch bestimmt die Sache mit dem Einheitskreis und dem rechtwinkligen Dreieck darin. Die Hypotenuse dieses Dreieckes ist dabei nämlich immer der Kreis-Radius, der, wenn der Winkeln zur X-Achse langsam aber stetig zunimmt, dann natürlich auch jeden Punkt auf dieser Kreisbahn berühren kann. Und um nun rechnerisch zu diesen Punkten auf der Kreisbahn zu kommen, brauchst man jetzt nur noch mehr zu einer Ausgangsposition diejenigen Längen dazuaddieren, die dieser Radius (=Hypotenuse) jeweils auf die X- u. auf die Y-Achse projiziert ergibt. Und genau diese Projektionslängen sind nunmal die Ergebnisse dieser Sinus- und Kosinus-Funktionen... (Wie die jetzt mathematisch genau definiert sind, wird ja schon teilweise darüber beschrieben)


edit: Die obige Erklärung gilt, wenn die dort erwähnte Ausgangsposition (X0/Y0) immer der Kreismittelpunkt ist ...und daher musste das X0 vor dem eigentlichen Start des Timers dann eben auch immer zuerst noch auf diesen Kreismittelpunkt umgesetzt werden muss (X0 := Label1.left - 40)! ~~~ nur der absoluten Nachvollziehbarkeit halber ~~~


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz