Autor Beitrag
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: 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:
ausblenden 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:
ausblenden volle Höhe 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:
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
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  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 :lol:
Dragon777
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

XP Prof
D3 Prof
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Di 23.08.05 23:21 
user profile iconF34r0fTh3D4rk hat folgendes geschrieben:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mi 24.08.05 00:43 
Ähm ich bekomme eine Exception. Hier:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 41

XP Prof
D3 Prof
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Mi 24.08.05 13:58 
komischerweise verliert der ball bei mir an y energie, liegt das an rundungsungenauigkeiten ?
ausblenden volle Höhe 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:
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
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mi 24.08.05 16:57 
user profile iconAllesquarks 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 Suche in: Delphi-Forum, Delphi-Library RKM4.

user profile iconAllesquarks 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).

user profile iconAllesquarks 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mi 24.08.05 21:09 
Und woher kommt nun die Zugriffsverletzung? :shock:

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Fr 09.09.05 13:44 
ich habs etwas korrigiert, aber der fehler besteht weiterhin:
ausblenden volle Höhe 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:
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; //meter in pixel umrechnen
begin
  Ball.yspeed := Ball.yspeed + 9.81 * (1000 / timer1.interval); //Beschleunigen mit 9.81 m/s²
  Ball.y := Ball.y + Ball.yspeed / meter; //Neue Höhe setzen
  if Ball.y + Ball.radius >= image1.ClientHeight then //Vom Boden abprallen
    begin  
      Ball.y := image1.ClientHeight - ball.radius;
      Ball.yspeed := - Ball.yspeed;
    end;

  //image1.picture := nil;

  with image1.canvas do //Canvas leeren
    begin
      brush.color := clwhite;
      pen.color := clwhite;
      rectangle(0, 0, image1.width, image1.height);
    end;
  Ball.Draw; //Ball zeichnen
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 ?