Entwickler-Ecke

Sonstiges (Delphi) - Objekt in SInuskurve bewegen!


InfocrackUrsula - Fr 24.02.12 13:41
Titel: Objekt in SInuskurve bewegen!
Hallo,
ich würde gerne eine Luftblase als eingefügtes Image sinusförmig von unten nach oben wandern lassen. Wenn die Luftblase oben verschwunden ist, soll sie an einem zufälligen x-wert an der unteren leiste erneut aufsteigen. Delphi akzeptiert leider nicht DegToRad und bezeichnet es als undefinierten bezeichner. Habt ihr irgendwelche Ideen?
Hier der bisherige Quelltext:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.Timer1Timer(Sender: TObject);
var x, y, z : real ;
begin
      randomize;
      z:= random(500)+1;
      y:= DegToRad(Sin(x)) + z;
      y:= y+1;
      if y<0 then
      y := 465;
      bubble.top:=y;
      bubble.Left:=x;
(bubble steht für das eingefügte Image)
Vielen Dank für die Hilfe :D

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt und Color-Tags entfernt.


Gammatester - Fr 24.02.12 13:48

Um DegToRad zu benutzen, mußt Du die Unit Math einbinden: uses math; bzw in die schon vorhandene Uses-Anweisung einfügen.

Allerdings erscheint mir DegToRad(Sin(x)) nicht sinnvoll, Du meinst doch wahrscheinlich Sin(DegToRad(x)).


InfocrackUrsula - Fr 24.02.12 14:01

Danke ich hab jetzt uses math eingefügt, aber sobald wir Play drücken, kommt immer diese Meldung hier: Im Projekt Project1.exe ist eine Exception der Klasse EInvalidOp aufgetreten. Meldung: 'Invalid floatting point operation.' Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzten.
Was soll ich tun?

Moderiert von user profile iconNarses: Color-Tags entfernt.


ub60 - Fr 24.02.12 14:10

x wird gar nicht verwendet, außerdem müssen x und y Integer-Werte sein (wegen der ganzzahligen Pixel :) ). Irgendwie fehlt auch eine Schleife. Ach so, und y muss kleiner werden, wenn die Blase nach oben steigen soll.


Gammatester - Fr 24.02.12 14:13

Ich weiß zwar nicht; wo der Fehler auftritt, aber schau Dir mal Deinen Quellcode an (eigentlich sollte der Compiler auch Hinweise geben): x wird verwendet, ohne belegt zu sein! Deshalb enthält es höchst wahrscheinlich Schrottwerte von denen Du den Sinus berechnen willst. Was ist x? Es wird nur lokal verwendet!?

Noch ein paar Hinweise:


InfocrackUrsula - Fr 24.02.12 14:25

Ich benutze einen Timer und brauch doch dann keine Schleife oder?
Das integer und real Problem ist gelöst und er stürzt nicht mehr ab, aber unser Image zuckt auf einer bestimmten x-Achse hin&her und bewegt sich nicht nach oben. Was muss ich ändern?
Der Quelltext sieht jetzt so aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.Timer1Timer(Sender: TObject);
var x, z : Integer;
    y : real;
begin
      randomize;
      z:= random(500)+1;
      x:= z;
      y:= DegToRad(Sin(x) + z);
      y:= y-1;
      if y<0 then
      y := 465;
      bubble.top:=trunc(y);
      bubble.Left:=trunc(x);
end;
mfg

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


Xion - Fr 24.02.12 14:42

Um eine Animation zu machen musst du den Status global speichern, damit du beim nächsten Timer-Aufruf weißt wie weit du schon animiert hast.

Momentan startest du jedes mal beim Timer die Animation neu ( x:=random(500)+1; )

Also brauchst du zuerst mal eine "globale" Variable (animState) um zu speichern wie weit deine Animation abgelaufen ist, und außerdem musst du die Ausgangsposition, die du mit x wählst, speichern (animX). Alles was du lokal in der Funktion als var definierst, ist beim nächsten Aufruf weg.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
var animState: integer;
    animX: integer;
[...]
procedure TForm1.Timer1Timer(Sender: TObject);
begin
     if animState>??? then 
       begin
         //Animation neu starten
         animState:=-Bubble.Height;  
         ...//animX neu wählen
       end
     else
       begin
         //Animation einen Schritt weiter
         animState:=animState+1//einen Schritt weiter (auch mehr als +1 möglich => schnellere Animation)
         Bubble.Top := animState; 
         Bubble.Left := animX + round( sin(degtorad(animState))*42 );
       end;
end;


Ich hab ein paar Lücken zum selbst überlegen gelassen ;)


Gammatester - Fr 24.02.12 14:45

Ich hatte schon zwei Bemerkungen dazu gemacht. Deine x-Koordinate springt, weil Du sie zufallsmäßig so belegst. Was Du machen willst ist, ist doch wahrscheinlich eher ungefähr folgendes:

1. Wähle (zufällig) x=x0 aus
2. Wähle (zufällig?) y0 aus
3. Berechne y = y0 + A*sin(B*t) - C*t
4. Zeichne bei (x,y)
5. Wiederhole ab Schritt 3 bis y < 0
6. Gehe nach 1.

Zu 3: Die y-Koordinaten auf dem Schirm sind anders orientiert als mathematisch. Wenn Du C=0 setzt, würde y zwar schwingen, aber langfristig nicht ansteigen bzw. absinken. Als Argument für sin() willst Du doch wahrscheinlich irgendwie die Zeit haben und nicht zufällige x-Werte.


InfocrackUrsula - Fr 02.03.12 14:15

danke für nichts gammatester

Moderiert von user profile iconNarses: Color-Tags entfernt.