| Autor |
Beitrag |
F34r0fTh3D4rk
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Di 23.08.05 13:46
Hallo, ich wollte gerade mit einer kleinen simulation anfangen und zwar ein ball der fällt und dann wieder hichspringt, mein code sieht so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.Timer1Timer(Sender: TObject); begin Ball.y := Ball.y + round(Ball.yspeed / 100); if Ball.y + Ball.radius >= image1.ClientHeight then Ball.yspeed := - Ball.yspeed; Ball.yspeed := Ball.yspeed + 9.81; image1.picture := nil; Ball.Draw(image1.Canvas); end; |
Ist das so korrekt ? das timer intervall hab ich auf 10ms, obwohl ich das nicht ganz verstehe, die beschleunigung ist doch pro sekunden, also bei 1000ms, da tut sich aber recht wenig, wie muss ich das genau machen, damit das möglichst der wirklichkeit entspricht?
Wie bekomme ich meinen ball dazu, langsam immer niedriger zu springen, damit er irgendwann physikalisch korrekt zum stillstand kommt ? ich wollte das alles physikalisch so genau wie möglich haben
hab das eben auch nur schnell geproggt, weil ich das schon immer mal machen wollte, hatte aber keinen plan, wie ich die physikalischen gesetze da einbaue, jetzt habe ich einfach festgelegt, dass 1px = 1/100m ist und das scheint soweit zu klappen.
hier mal die gesamt-unit:
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: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls;
type TForm1 = class(TForm) Image1: TImage; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private public end;
type TBall = class x, y, radius: integer; xspeed, yspeed: double; color: TColor; procedure Draw(Canvas: TCanvas); end;
var Form1: TForm1; Ball: TBall;
implementation
{$R *.dfm}
procedure TBall.Draw(Canvas: TCanvas); begin with canvas do begin brush.color := color; ellipse(x - radius, y - radius, x + radius, y + radius); end; end;
procedure TForm1.FormCreate(Sender: TObject); begin doublebuffered := true; Ball := TBall.Create; with Ball do begin radius := 15; color := clred; x := Image1.Width div 2; y := Image1.Width div 8; xspeed := random(200) - 100; yspeed := 0; Draw(image1.Canvas); end; end;
procedure TForm1.Timer1Timer(Sender: TObject); begin Ball.y := Ball.y + round(Ball.yspeed / 100); Ball.x := Ball.x + round(Ball.xspeed / 100); if Ball.y + Ball.radius >= image1.ClientHeight then begin Ball.y := image1.ClientHeight - ball.radius; Ball.yspeed := - Ball.yspeed; end; if Ball.y - Ball.radius <= 0 then begin Ball.y := Ball.radius; Ball.yspeed := - Ball.yspeed; end; if Ball.x + Ball.radius >= image1.ClientWidth then begin Ball.x := image1.clientwidth - Ball.Radius; Ball.xspeed := - Ball.xspeed; end; if Ball.x - Ball.radius <= 0 then begin Ball.x := Ball.Radius; Ball.xspeed := - Ball.xspeed; end; Ball.yspeed := Ball.yspeed + 9.81; image1.picture := nil; Ball.Draw(image1.Canvas); end;
Initialization randomize;
end. |
der ball kommt doch zum liegen, es dauert aber ewig 
|
|
Dragon777
      
Beiträge: 41
XP Prof
D3 Prof
|
Verfasst: Di 23.08.05 15:31
bei mir wird kein ball angezeigt? warum bloß?
ich hab delphi 3 prof
den befehl doublebuffered gibts bei mir nicht
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Di 23.08.05 18:35
doublebuffered kannst du bei delphi3 auch vernachlässigen, das ist nur gegen das flackern. wie groß ist denn dein image1 ?
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Di 23.08.05 23:21
F34r0fTh3D4rk hat folgendes geschrieben: | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.Timer1Timer(Sender: TObject); begin Ball.y := Ball.y + round(Ball.yspeed / 100); if Ball.y + Ball.radius >= image1.ClientHeight then Ball.yspeed := - Ball.yspeed; Ball.yspeed := Ball.yspeed + 9.81; image1.picture := nil; Ball.Draw(image1.Canvas); end; |
Ist das so korrekt ? |
Fast. Es müsste Ball.yspeed := Ball.yspeed + 9.81/100; lauten, d.h. 1/100 (= Intervall/1000) fehlt. Allerdings ist dann deine Beschleunigung 9.81 Pixel pro Sekunde^2. Das ist im Vergleich zu 9.81 m/s^2 etwas weniger
Ausserdem würde ich die Variablen x und y mit Doubles rechnen.
Physikalisch korrekt zum Stillstand kommen: Physikalisch korrekt kommt der Ball nie zum Stillstand, denn er deformiert sich beim Aufprall ja nicht und sollte für immer und ewig gleich hoch springen (es geht keine Energie verloren). Wenn du willst, dass der Ball nicht immer gleich hoch springt, musst du beim Aufprall Energie aus dem System ziehen (Deformationsenergie). Dieser Verlust kannst du als proportional zur Aufprallgeschwindigkeit annehmen. Also sowas wie Ball.yspeed := - Verlustfaktor*Ball.yspeed; (0<Verlustfaktor<1). Dann hast du exponentiell abklingende Höhen; kommt also theoretisch auch nie zum Stillstand. Du müsstest also noch eine Toleranz festlegen, unter welcher die gesamte Geschwindigkeit senkrecht zur Wandrichtung verloren geht.
Ausserdem könntest du eine Luftreibung einbauen. Die ist ungefähr proportional zur Momentangeschwindigkeit.
Was auch noch fehlt ist die Wandreibung. Der Ball gleitet an der Wand und rotiert somit nie. Wenn du die Rotation berücksichtigen willst wird's allerdings komplizierter. Da müsstest du für den Ball ein Trägheitsmoment definieren und ihn als Starrkörper simulieren. Rotationen von Körpern in einem Fluid wie Luft können zudem Auftriebe induzieren ("Topspin", etc.).
Tja, umso mehr physikalische Effekte du willst, desto komplizierter wird's. 
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Mi 24.08.05 00:43
Ähm ich bekomme eine Exception. Hier:
Delphi-Quelltext 62: 63: 64: 65:
| { ... } procedure TForm1.Timer1Timer(Sender: TObject); begin Ball.y := Ball.y + round(Ball.yspeed / 100); Ball.x := Ball.x + round(Ball.xspeed / 100); |
Eine Zugriffsverletzung, ihr wisst schon, die alte Leier... Hab ich was falsch gemacht? oO
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Mi 24.08.05 08:34
1)Deine Ballbahn berechnest Du ja sowieso nicht korrekt, da die Strecke ja eigentlich 1/2*a*t² wäre. Allerdings ist deine Methode so ähnlich wie die archimedische STreifenmehtode beim integerieren (also nur genau bei vielen Schritten und desto ungenauer je länger die Simulation läuft). Wenn Du also noch Ressurcen hast dann würde ihc kleinere Schritte als 100 ms nehmen.
2)Must Dich entscheiden ob der SToßr elastisch oder inelastisch sein soll. Wie schon von delfiphan erwähnt verliert er sonst keine höhe. Ein Abklingfaktor ist hierfür physikalisch gut geeignet.
3) Theama Reibung: Wird in der Physik hauptsächlich unterschieden zwischen laminarer und turbulenter Strömung, wobei erstere hier schon erläutert wurde und zweitere unter das Stichwort newtonsche Reibung (F=a*v²) (bei hohen GEschwindigkeiten genauere Bestimmung der Grenzgeschwindigkeit über Reynoldszahl)fällt. Beide werden als Differentialgleichungen formuliert und sind selten analytisch zu lösen, weshalb dort die STärke deines Ansatzes liegt, da man dieses Problem mit schrittweisen weitergehen "simulieren" (Wenn Schrittzahl gegen unendlich dann geht Genauigkeit ebenfalls gegen unendlich).
|
|
Dragon777
      
Beiträge: 41
XP Prof
D3 Prof
|
Verfasst: Mi 24.08.05 09:34
Also bei stimmt da noch was nicht.
Bei uses- Variants sagt er mir datei Variants.dcu nicht gefunden.
und bei doublebuffered sagt er nicht definierter bezeichner
Mein Image wird doch angezeigt es ist 100x100.Aber es bewegt sich nicht.
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Mi 24.08.05 13:58
komischerweise verliert der ball bei mir an y energie, liegt das an rundungsungenauigkeiten ?
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: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
| type TForm1 = class(TForm) Image1: TImage; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private public end;
type TBall = class x, y, radius: double; yspeed: double; color: TColor; procedure Draw(Canvas: TCanvas); end;
var Form1: TForm1; Ball: TBall;
implementation
{$R *.dfm}
procedure TBall.Draw(Canvas: TCanvas); begin with canvas do begin brush.color := color; ellipse(round(x - radius), round(y - radius), round(x + radius), round(y + radius)); end; end;
procedure TForm1.FormCreate(Sender: TObject); begin doublebuffered := true; Ball := TBall.Create; with Ball do begin radius := 15; color := clred; x := Image1.Width div 2; y := Image1.Width div 8; yspeed := 0; Draw(image1.Canvas); end; end;
procedure TForm1.Timer1Timer(Sender: TObject); begin Ball.yspeed := Ball.yspeed + (9.81 / (timer1.interval / 1000)); Ball.y := Ball.y + Ball.yspeed / 1000; if Ball.y + Ball.radius >= image1.ClientHeight then begin Ball.y := image1.ClientHeight - ball.radius; Ball.yspeed := - Ball.yspeed; end; if Ball.y - Ball.radius <= 0 then begin Ball.y := Ball.radius; Ball.yspeed := - Ball.yspeed; end; image1.picture := nil; Ball.Draw(image1.Canvas); end;
Initialization randomize;
end. |
mit zunehmendem interval und sinkendem maßstab wird der ball ziemlich schnell.
so würde er beim aufprall an energie verlieren:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.Timer1Timer(Sender: TObject); begin Ball.yspeed := Ball.yspeed + (9.81 / (timer1.interval / 1000)); Ball.y := Ball.y + Ball.yspeed / 1000; if Ball.y + Ball.radius >= image1.ClientHeight then begin Ball.y := image1.ClientHeight - ball.radius; Ball.yspeed := - Ball.yspeed * 0.35; end; image1.picture := nil; Ball.Draw(image1.Canvas); end; |
aber er verliert zwischendrin so schon energie, ohne diesen faktor, warum ?
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 24.08.05 16:57
Allesquarks hat folgendes geschrieben: | | 1)Deine Ballbahn berechnest Du ja sowieso nicht korrekt, da die Strecke ja eigentlich 1/2*a*t² wäre. Allerdings ist deine Methode so ähnlich wie die archimedische STreifenmehtode beim integerieren (also nur genau bei vielen Schritten und desto ungenauer je länger die Simulation läuft). Wenn Du also noch Ressurcen hast dann würde ihc kleinere Schritte als 100 ms nehmen. |
Er verwendet die sog. Euler-Integration; konvergiert also linear mit dt zur exakten Lösung. Für eine genauere Integration siehe RKM4.
Allesquarks hat folgendes geschrieben: | | 2)Must Dich entscheiden ob der SToßr elastisch oder inelastisch sein soll. Wie schon von delfiphan erwähnt verliert er sonst keine höhe. Ein Abklingfaktor ist hierfür physikalisch gut geeignet. |
Der Stoss ist weder völlig elastisch noch völlig inelastisch, sondern etwas zwischen drin. Ein Abklingfaktor beim Impulsaustausch ist wohl tatsächlich das beste (und das einfachste).
Allesquarks hat folgendes geschrieben: | | 3) Theama Reibung: Wird in der Physik hauptsächlich unterschieden zwischen laminarer und turbulenter Strömung, wobei erstere hier schon erläutert wurde und zweitere unter das Stichwort newtonsche Reibung (F=a*v²) (bei hohen GEschwindigkeiten genauere Bestimmung der Grenzgeschwindigkeit über Reynoldszahl)fällt. Beide werden als Differentialgleichungen formuliert und sind selten analytisch zu lösen, weshalb dort die STärke deines Ansatzes liegt, da man dieses Problem mit schrittweisen weitergehen "simulieren" (Wenn Schrittzahl gegen unendlich dann geht Genauigkeit ebenfalls gegen unendlich). |
Turbulente Strömung numerisch zu lösen kannst du eh grad vergessen. Um die Turbulenz mittels direkter numerischer Simulation zu berechnen brauchst du spezielle Methoden und ein sehr feines Gitter. In Echtzeit absolut unmöglich. Zudem existiert in 2D keine turbulente Strömung.
Du kannst aber den Fall der Potentialströmung annehmen und die Auftriebsformel von Kutta-Joukowski verwenden (um den Auftrieb zu berücksichtigen). Aber ich denke nicht, dass du die Rotation berücksichtigen willst. Und wenn, dann ohne die ganze Fluiddynamik drumherum 
|
|
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Mi 24.08.05 17:14
Wollte eigentlich nur das Stichwort Newtonsche Reibung nicht ganz Zusammenhanglos darstellen lassen.
Das mit dem Integral hab ich auch nur erwähn, um die Verfahren zu erläutern, weil ich das Gefühl hatte das er davon ausgeht s=v*t und v=a*t was aber natürlich nicht für alle Fälle gilt. Und beides auf einmal schon gar nicht!
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 24.08.05 17:21
s=v*t und v=a*t nicht, aber s(t+dt)=s(t)+v(t)*dt und v(t+dt)=v(t)+a(t)*dt (**). Genau das hat er implementiert (bzw. fast).
(**) In erster Näherung. Das ganze nennt sich "Euler-Methode" und folgt direkt aus der Taylorentwicklung wenn man nach der ersten Ableitung abbricht. "dt" ist in seinem Fall das Zeitintervall (falls er keine Zwischenschritte berechnet). Also dt=Timer1.Interval/1000, wenn man in Sekunden rechnet.
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Mi 24.08.05 21:09
Und woher kommt nun die Zugriffsverletzung? 
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
F34r0fTh3D4rk 
      
Beiträge: 5285
Erhaltene Danke: 29
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Fr 09.09.05 13:44
ich habs etwas korrigiert, aber der fehler besteht weiterhin:
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: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72:
| type TBall = class xspeed, yspeed: double; x, y: double; radius: integer; color: TColor; Canvas: TCanvas; procedure Draw; end;
var Form1: TForm1; Ball: TBall;
implementation
{$R *.DFM}
procedure TBall.Draw; begin with Canvas do begin pen.color := clblack; pen.width := 2; brush.color := Color; ellipse(round(x - radius), round(y - radius), round(x + radius), round(y + radius)); end; end;
procedure TForm1.FormCreate(Sender: TObject); begin Ball := TBall.Create; with Ball do begin radius := 20; x := image1.width div 2; y := radius; xspeed := 0; yspeed := 0; color := clred; Canvas := image1.Canvas; end; end;
procedure TForm1.Timer1Timer(Sender: TObject); const meter = 50; begin Ball.yspeed := Ball.yspeed + 9.81 * (1000 / timer1.interval); Ball.y := Ball.y + Ball.yspeed / meter; if Ball.y + Ball.radius >= image1.ClientHeight then begin Ball.y := image1.ClientHeight - ball.radius; Ball.yspeed := - Ball.yspeed; end;
with image1.canvas do begin brush.color := clwhite; pen.color := clwhite; rectangle(0, 0, image1.width, image1.height); end; Ball.Draw; end;
procedure TForm1.Button1Click(Sender: TObject); begin Ball.yspeed := 0; Ball.y := Ball.radius; end; |
mein info lehrer sagt, dass das physikalisch doppelt ist, ich meine aber das ist richtig, wo liegt der fehler ?
|
|
|