Autor Beitrag
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Mo 19.02.07 11:37 
HI,

es gab vor ein paar wochen schonma so'n Thema. das hat mich auf die Idee gebracht n Billjardspiel zu programmieren. Nun ist das eintige woran es hängt die berechnung wie sich die beiden Kugeln voneinander abstoßen. Ich hab schon edliche Skizzen gemacht und irgedwie versucht mit Winkelfkt. die Flugbahn zu berechnen aber ich komm einfach nicht dahinter. Kann mir da jemand helfen?! Die rein physikalische Formel würde reichen umsetzung in Delphi müsste ich selber hin bekommen.

MfG & Thx Bergmann.
rockminstrel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 38

Win XP Prof.
Delphi 5 Prof., Delphi 2005 pers., Turbo Delphi 2006 Exp.
BeitragVerfasst: Mo 19.02.07 11:44 
Also eigentlich müsste es so sein: (Billardbeispiel) die rote Kugel bewegt sich geradlinig in die Richtung, die Berührungspunkt mir der weißen ugel und Zentrum bilden. Deswegen testen die Spieler oft, wo man die rote Kugel treffen muss um sie direkt ins Loch zu stoßen.

Was ich dir nicht sagen kann ist wohin die weiße Kugel geht nachdem Sie die rote berührt hat.
Dragonclaw
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 196

Windows Vista
Delphi 7 Prof.
BeitragVerfasst: Mo 19.02.07 11:48 
Hallo,

das ganze nennt sich dezentraler elastischer Stoß.

Es gab mal einen Beitrag hier im Forum wo jemand genau dieses Problem gelöst hatte. Ich würde hier gerne delfiphan quoten, aber der Beitrag scheint down zu sein. Hier mal der Link: www.delphi-forum.de/...=tkugel+class+tshape

Allerdings habe ich mir damals den Code geladen und hab den auch noch wieder gefunden. Hier ist der Code:

Zitat:
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:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
unit Unit1;

interface

uses
  SysUtils, Forms, StdCtrls, ExtCtrls, Classes, Controls;

const
 dt = 20// in ms
 SubIterations = 20;
 KugelCount = 10;

type
  TKugel = class;

  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    Kugeln: array[0..KugelCount-1of TKugel;
  end;

  Borders = (boLeft, boTop, boBottom, boRight);
  BordersSet = set of Borders;
  TKugel = class(TShape)
  private
    FX, FY: Extended;
    FR: Extended;
    FM: Extended;
    FVx, FVy: Extended;
    procedure setR(const Value: Extended);
  public
    property X: Extended read FX write FX; // Position [Pixel]
    property Y: Extended read FY write FY;
    property R: Extended read FR write setR; // Radius [Pixel]
    property M: Extended read FM write FM; // Masse
    property Vx: Extended read FVx write FVx; // Geschwindigkeit [Pixel/s]
    property Vy: Extended read FVy write FVy;
    procedure Move; // Nächster Zeitschritt
    procedure Apply;
    function CollidesWith(const Kugel2: TKugel): Boolean;
    function WallCollisions: BordersSet;
    constructor Create(AOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

 { TKugel }

function TKugel.CollidesWith(const Kugel2: TKugel): Boolean;
begin
  Result := sqr(FX-Kugel2.FX)+sqr(FY-Kugel2.FY) < sqr(FR+Kugel2.FR);
end;

constructor TKugel.Create(AOwner: TComponent);
begin
  inherited;
  Shape := stCircle;
end;

procedure TKugel.Move;
begin
  X := X + (dt/1000)/SubIterations*FVx; // ms => s
  Y := Y + (dt/1000)/SubIterations*FVy;
end;

function TKugel.WallCollisions: BordersSet;
const
  Border = 10;
begin
  Result := [];
  if X-Border < R then // links über Rand
   Result := Result + [boLeft];
  if Y-Border < R then // oben über Rand
   Result := Result + [boTop];
  if X+Border >= Parent.ClientWidth-R then // rechts über Rand
   Result := Result + [boRight];
  if Y+Border >= Parent.ClientHeight-R then // unten über Rand
   Result := Result + [boBottom];
end;

procedure TKugel.setR(const Value: Extended);
begin
  FR := Value;
  Width := Round(FR*2); // Grösse des Shapes mitändern
  Height := Round(FR*2);
end;

procedure TKugel.Apply;
begin
  Left := round(X-FR); // Position des Shapes anpassen
  Top := round(Y-FR);
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
const
 Border = 10;
var
 I: Integer;
begin
  // Timer initialisieren
  with Timer1 do
  begin
   Interval := dt;
   OnTimer := Timer1Timer;
  end;

  // Kugeln zufällig in den Raum platzieren
  for I := 0 to Length(Kugeln)-1 do
  begin
    Kugeln[I] := TKugel.Create(Form1);
    with Kugeln[I] do
    begin
     Parent := self;
     R := 20+Random(8);
     X := Random(self.ClientWidth-2*Round(R+Border))+Round(R+Border);
     Y := Random(self.ClientHeight-2*Round(R+Border))+Round(R+Border);
     Vx := Random(400);
     Vy := Random(400);
     M := 4/3*R*R*R*pi;
     Brush.Color := Random(256*256*256); // farbige Bälle
    end;
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
 DX, DY, M11, M21, M12, M22, L, Vp1, Vp2, Vs1, Vs2, MTot, Vp1_, Vp2_: Extended;
 I, J, K: Integer;
 B: BordersSet;
begin
  for K := 0 to SubIterations-1 do
  begin
   // Position nachführen (gemäss gegebenen Geschwindigkeiten)
   for I := 0 to Length(Kugeln)-1 do
    Kugeln[I].Move; 

   // Kollisionserkennung zwischen Kugeln
   for I := 0 to Length(Kugeln)-1 do
    for J := I+1 to Length(Kugeln)-1 do // über alle geordneten Paare
     // Falls Kollision zwischen Kugel I und Kugel J:
     if Kugeln[I].CollidesWith(Kugeln[J]) then
     begin
      DX := Kugeln[j].X-Kugeln[i].X; // Delta x
      DY := Kugeln[j].Y-Kugeln[i].Y; // Delta y
      L := sqrt(sqr(DX)+sqr(DY)); // Abstand
      // Matrix mit neuen Koordinatenachsen (parallel/senkrecht zum Stoss)
      M11 := DX/L; M12 := -DY/L;
      M21 := DY/L; M22 := DX/L;

      // Koordinatentransformation
      Vp1 := Kugeln[i].Vx*M11+Kugeln[i].Vy*-M12;
      Vs1 := Kugeln[i].Vx*-M21+Kugeln[i].Vy*M22;
      Vp2 := Kugeln[j].Vx*M11+Kugeln[j].Vy*-M12;
      Vs2 := Kugeln[j].Vx*-M21+Kugeln[j].Vy*M22;

      if Vp1-Vp2<0 then
       Continue; // Bälle gehen bereits auseinander
      // Zentraler Stoss
      MTot := Kugeln[i].M+Kugeln[j].M;
      Vp1_ := (Kugeln[i].M-Kugeln[j].M)/MTot*Vp1+2*Kugeln[j].M/MTot*Vp2;
      Vp2_ := (Kugeln[j].M-Kugeln[i].M)/MTot*Vp2+2*Kugeln[i].M/MTot*Vp1;

      // Rücktransformation
      Kugeln[i].Vx := Vp1_*M11+Vs1*M12;
      Kugeln[i].Vy := Vp1_*M21+Vs1*M22;
      Kugeln[j].Vx := Vp2_*M11+Vs2*M12;
      Kugeln[j].Vy := Vp2_*M21+Vs2*M22;
     end;

   // Wandkollisionen
   for I := 0 to Length(Kugeln)-1 do
    with Kugeln[I] do
    begin
     B := WallCollisions;
     if ((boLeft in B) and (Vx < 0)) or ((boRight in B) and (Vx > 0)) then 
      Vx := -Vx;
     if ((boTop in B) and (Vy < 0)) or ((boBottom in B) and (Vy > 0)) then
      Vy := -Vy;
    end;
   end// for K
  for I := 0 to Length(Kugeln)-1 do
   Kugeln[I].Apply; // Angezeigte Position updaten
end;

end.

Corpsman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 228

KUbuntu 10.4
Lazarus
BeitragVerfasst: Mo 19.02.07 11:49 
Das wurde echt schon zig mal gefragt.

Schau dir einfach mal das
Sample
an.

_________________
--
Just Try it.
Bergmann89 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Di 20.02.07 08:19 
OK, das hab ich gesucht...
Werd mich da jetzt erstma Durcharbeiten, DANKE.

Gibts da auch noch ne genaue Erklärung dazu, denn die Variablen sind
nicht grad aussagefähig, mit manchen Befehlen weiß ich nicht viel
anzufangen und erläuterungen sind auch nicht sehr viele drin.
Ich will ja nicht meckern, aber wenn ich das bloß abscreib hab ich auch
nix davon...
reptile
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 40



BeitragVerfasst: Mo 02.04.07 18:33 
ich habe mir das beispiel mal angesehen und muss bergmann89 recht geben: es wäre schön wenn das ganze besser auskommentiert wäre, nicht jeder kommt so hinter die variablenbezeichnungen.
ich verstehe zwar das vorgehen grob und es funktioniert auch wenn ich es einbaue, aber kann mir jemand die variablen:
M11, M21, M12, M22, Vp1, Vp2, Vs1, Vs2, Vp1_, Vp2_
erklären ?
ich vermute die M-s sind die neuen koordinatenachsen ? aber was ist Vp und Vs?

tut mir leid da kugel-kollision bestimmt schon tausendmal durchgekaut wurde, aber es ist für anfänger kein leichtes thema ^^
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Di 03.04.07 00:12 
Der FAQ-Beitrag berechnet den elastischen Stoss für Kugeln verschiedener Grössen und Massen. Bei Billardkugeln gibt es einfachere Formeln, da die Massen und Kugelradien für alle Kugeln gleich sind. Die Kugeln gehen dann z.B. immer im rechten Winkel zueinander auseinander.