![]() |
canvas - waagerechter wurf mit timer
hi leute,
ich hab ne schulaufgabe bekommen, an der ich absolut nicht weiterkomme. die aufgabe lautet: stelle mittels canvas einen strahl aus einem loch aus einer defekten wasserleitung dar. - die lochhöhe, sowie die geschwindigkeit des wassers sind per eingabe vorgegeben. desweiteren soll festgestellt werden, ob der strahl in einen eimer trifft, dessen position man ebenfalls per eingabe verändern kann. das ganze sieht derzeit wie folgt aus: ![]() input: lochhöhe = h geschwindigkeit = v eimerposition = e output: wurfweite = w sonst habe ich noch 3 dinge umbenannt: Form1 = frm Image1 = img Timer = tmr
Code:
nun habe ich das problem, dass
procedure buildimg (e: Integer);
begin clearimg; with frm.img.canvas do begin // Leitung brush.color:=$00CCCCCC; pen.color:=$00000000; rectangle(10,0,20,frm.img.height); // Eimer brush.color:=$0066FF66; pen.color:=$00448844; rectangle(20+e,frm.img.height-20,40+e,frm.img.height); end; end; procedure circle (x,y: Integer); begin with frm.img.canvas do begin // Loch & Kreise brush.color:=$00FF6666; pen.color:=$00884444; ellipse(x,y,x+5,y+5); end; end; procedure Tfrm.Button1Click(Sender: TObject); begin // Eingabe a:=9.81/2; h:=strtoint(edt_in_h.text); v:=strtofloat(edt_in_v.text); e:=strtoint(edt_in_e.text); if (h<300) and (h>-1) and (e<261) and (e>-1) and (v>0) then begin x:=15; y:=frm.img.height-h; buildimg(e); circle(x,y); frm.tmr.enabled:=true; end else edt_out_w.text:='FEHLER!'; end; procedure Tfrm.tmrTimer(Sender: TObject); begin if (y<frm.img.height) then begin // y:=y+25; y:=y+round((a*x*x/(v*v))/150); x:=x+round(v*sqrt((y)/a)); circle(x,y); end else begin w:=x; edt_out_w.text:=inttostr(w); frm.tmr.enabled:=false; end; end; 1. w nicht korrekt ausgegeben wird. das sieht man ja auf dem bild. der eimer ist 20pixel breit und der letzte wasserkreis sollte ja in dem eimer sein.) 2. ich keine regelmäßigen abstände nach unten habe, da y durch das intervall 150 geteilt wird. wenn ich stattdessen y:=y+25; (was hier auskommentiert ist) festlege, kommt seltsamerweise keine parabel mehr zustande. x wird irgendwie falsch berechnet - ich weiß nicht, warum. 3. der letzte wassertropfen sollte direkt auf dem boden aufkommen, da x aber wie gesagt falsch berechnet wird, kriege ich das nicht hin. ich habe es schon wie folgt ausprobiert:
Code:
wobei er aber x wieder falsch ausgibt. ich bin hier wirklich am verzweifeln. außerdem frage ich mich, wieso ich das überhaupt in einem timer ausgeben muss (teil der aufgabe).
procedure Tfrm.tmrTimer(Sender: TObject);
begin if (y<frm.img.height) then begin // y:=y+25; y:=y+round((a*x*x/(v*v))/150); x:=x+round(v*sqrt((y)/a)); circle(x,y); end else begin y:=frm.img.height-5; x:=round(v*sqrt((y)/a)); w:=x; edt_out_w.text:=inttostr(w); frm.tmr.enabled:=false; end; end; ich bin echt für jede hilfe dankbar. |
Re: canvas - waagerechter wurf mit timer
Hallo tar,
hier werden ja keine Hausaufgaben gelößt, dennoch möchte ich Dir einen Denkanstoß geben. Der Waagrechte Wurf besteht ja aus zwei getrennten Bewegungen. 1. Bewegung in x-Richtung Da diese Berechnung von einer reibungslosen Umgebung ausgeht, heißt das bei einer Geschwindigkeit V>0 ändert sich der Weg in X-Richtung linear (s = v*t). Bitte im Code beachten was passiert bei v = 0 !!! 2. Bewegung in y-Richtung Da hier keine Anfangsgeschwindigkeit vorhanden ist (also Vy=0) wirkt nur die Erdbeschleunigung. Die Formel s = 1/2 * a *t^2 zeigt einem ja schon, dass der Weg in Y-Richtung von Zeitschritt zu Zeitschritt (Timer-Event) Größer wird (t geht quadratisch ein). -> Folge wie auf der Abbildung zu sehen ist ist eine nach unten geöffnete Parabel. Lösungsansatz: Berechne im Timer mal nur mit diesen Formeln x und y. D.h.
Delphi-Quellcode:
Das sollte, wie ich denke als Hilfestellung reichen :-)
// Vor der Timer-Routine:
TimerCount := 0; v := ... h := ... //in der TimerRoutine: inc(TimerCount); t := TimerCount * Timer.Interval / 1000; x := v * t; // Achtung: Hier muss danach noch die Koordinatenumrechnung auf die Canvas erfolgen y := h - 0.5 * 9.81 * t; // Achtung: Hier muss noch die Koordinatenumrechnung auf die Canvas erfolgen Gruß, Chris |
Re: canvas - waagerechter wurf mit timer
Du solltest zunächst einmal die Formel für den schrägen Wurf in einer eigenen Function isolieren.
Überleg dir, welche Parameter in die Formel reinkommen (Gewschwindigkeit, Winkel, Zeit, ...) und was das Ergebnis ist. Die Formel sollte davon ausgehen, dass der Wurf auf Höhe 0 gestartet wird. Denk daran, dass es für Punkte den Datentyp TPoint gibt; du brauchst also x- und y-Wert nicht in 2 Variablen übergeben. |
Re: canvas - waagerechter wurf mit timer
Hallo!
zu 1. das verstehe ich nicht ganz... ist denn da nicht einfach nur die Position falsch angegeben? zu 2. naja, eine Parabel bekommst du glaub ich auch nur, wenn du in der Formel irgendwo was mit x^2 drin hast oder nicht? zu 3. du fängst doch von dem Rohr an gesehen zu rechnen, oder? vielleicht kannst du ja eine "Abschlussberechnung" für den letzten Tropfen bei x=0 (also dem Boden) zusätzlich machen oder du musst bei jedem Tropfen ein Offset abziehen, was dann aber auch die Kurve verschiebt. |
Re: canvas - waagerechter wurf mit timer
Lass die Finger lieber weg von so gleichungen wie für den schrägen Wurf. Wenn du das nicht herleiten kannst, ist es Unsinn, sowas zu nutzen. Die beste Methode ist sicher die von Chris. Du hast zwei getrennte Funktionen, eine für x, eine für y. Beide sind sehr einfach. (konstante geschwindigkeit und konstante Beschleunigung)
Du nimmst also zwei Funktionen x(t) und y(t), die dir jeweils einen real, oder sowas, geben. Für jeden Zeitpunkt kannst du dir dann die Position berechnen. Damit ist auch die Berechnung für den Eimer einfacher, als Pixel zu zählen: Du kannst dir ausrechnen, wann der Tropfen landen (da ist y(t)=0). Du hast also so eine gleichung wie y(t)=Fallhöhe-g/2t^2=0 damit kannst du dann t bestimmen. Wenn du diese zeit dann in x(t) eingibst, weisst du, wo der Tropfen landet. Das kannst du dann mit der Eimerkoordinate vergleichen (if eimer.x-10<tropfen<eimer.x+10) oder so. |
Re: canvas - waagerechter wurf mit timer
hallo ChrisE,
ich habe ein wenig herumprobiert. deine methode ändert nichts an den problemen, sie verkürzen nur das zeitinterval, welches aber nichts an den y-abständen ändert (durch beschleunigung wohl nicht möglich). ich bin weiterhin am verzweiffeln, wie genau er das (vor allem letzte X) ausrechnet. die koordinaten stimmen einfach irgendwie nicht - trotz verwendung der richtigen formeln. sieht man deutlich an diesem bild: ![]()
Delphi-Quellcode:
rest wie oben
procedure Tfrm.Button1Click(Sender: TObject);
begin // Eingabe a:=9.81/2; h:=strtoint(edt_in_h.text); v:=strtofloat(edt_in_v.text); e:=strtoint(edt_in_e.text); if (h<300) and (h>-1) and (e<281) and (e>19) and (v>0) then begin i:=0; x:=15; y:=frm.img.height-h; buildimg(e); circle(x,y); frm.tmr.enabled:=true; end else edt_out_w.text:='Eingaben falsch!'; end; procedure Tfrm.tmrTimer(Sender: TObject); begin if (y<frm.img.height) then begin inc(i); t:=i*frm.tmr.interval/50; y:=y+(a*t); x:=15+(v*t); circle(x,y); end else begin w:=round(x); if (w>e) and (w<e+20) then begin edt_out_w.text:=inttostr(w)+' Treffer!'; frm.tmr.enabled:=false; end else begin edt_out_w.text:=inttostr(w)+' Daneben!'; frm.tmr.enabled:=false; end; end; end; |
Re: canvas - waagerechter wurf mit timer
hallo Nikolas,
das mit der formel und der zeit bei y=0 (also eigentlich y=frm.img.height (in meinem fall 300)) kriegst du nicht gebacken, da: y = y+(a*t) umgestellt nach t: t = (y-y)/a = 0/a = 0 ergibt! damit bleibt für die rechnung von x kein zeitfaktor übrig: x = 15+(v*t) = 15+0 anders gerechnet, kommt bei x irgendwas dubioses raus: y = a*t = 300 t = y/a = 300/a x = 15+(v*t) wobei der ausgebene wert immer weit vom "strahl" entfernt ist. ich muss irgendwas übersehen. |
Re: canvas - waagerechter wurf mit timer
Zitat:
Zitat:
|
Re: canvas - waagerechter wurf mit timer
ja nikolas, ich habe ganz einfach y nicht mit der höhe gleichgesetzt, sondern mit den bild-koordinaten (also 300-höhe), was ja nicht funktionieren konnte und so hat er immer falsch gerechnet. ich musste die koordinaten später beim kreismalen nur anpassen und nun klappts.
also, ich habe die berechnung jetzt hinbekommen, allerdings immer noch ein problem: es gibt nun die 2 formeln: x = v * t y = g/2 * t² daraus ergibt sich für die zeit: t = x / v t = sqrt(2*y/g) daraus ergeben sich für x und y: x = v * sqrt(2*y/g) y = g/2 * x*x / (v*v) hiermit wird die zeit einfach nicht mehr benötigt! demzufolge ergibt sich nun folgender code:
Delphi-Quellcode:
das problem ist nun, dass das programm y irgendwie nicht immer rechtzeitig abfangen kann und dann einen fehler erzeugt:
procedure circle (x,y: Real);
begin with frm.img.canvas do begin // Loch & Kreise brush.color:=$00FF6666; pen.color:=$00884444; ellipse(round(x),frm.img.height-round(y),round(x)+5,frm.img.height-round(y)+5); end; end; procedure Tfrm.Button1Click(Sender: TObject); begin // Eingabe a:=9.81/2; h:=strtoint(edt_in_h.text); v:=strtofloat(edt_in_v.text); e:=strtoint(edt_in_e.text); if (h<300) and (h>-1) and (e<281) and (e>19) and (v>0) then begin i:=0; x:=15; y:=h; buildimg(e); circle(x,y); frm.tmr.enabled:=true; end else edt_out_w.text:='Eingaben falsch!'; end; procedure Tfrm.tmrTimer(Sender: TObject); begin if (y>5) then // Versuch, abzufangen begin y:=y-((a * x*x / (v*v))/frm.tmr.interval); x:=x+((v * sqrt(y/a))/frm.tmr.interval); circle(x,y); end else begin w:=round(x); if (w>e-1) and (w<e+21) then begin edt_out_w.text:=inttostr(w)+' Treffer!'; frm.tmr.enabled:=false; end else begin edt_out_w.text:=inttostr(w)+' Daneben!'; frm.tmr.enabled:=false; end; end; end; "invaliding float point operation." und auf diese zeile verweist:
Delphi-Quellcode:
nur habe ich das aber doch schon abgefangen mit y>5, so dass er gar nicht "über den bildrand" darf?
y:=y-((a * x*x / (v*v))/frm.tmr.interval);
x:=x+((v * sqrt(y/a))/frm.tmr.interval); // <-- diese und wieso kann er nicht mit y<5 rechnen? selbst wenn y negativ wär? den kreis würde man ja eh nicht mehr sehen. |
Re: canvas - waagerechter wurf mit timer
Ich hab jetzt nicht die ganze Disskussion mitverfolgt aber ich denke das Umstellen nach t
Zitat:
Ich würde einfach eine Formel nach t umstellen und die in die andere einsetzen. Zitat:
Die Umsetzeung mit Delphi gestaltet sich dannnoch etwas anders, aber das mathematisch/physikalische Problem ist imho damit gelöst. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:37 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-2025 by Thomas Breitkreuz