Autor Beitrag
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Fr 03.03.06 16:38 
Ich steh grad mal wieder aufm schlauch :P

ich habe hier meine prozedur für elastische nicht zentrale stöße:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure wocollide(var wo1, wo2: TWO);
  function checkcollision: boolean;
  begin
    result := sqr(wo1.posi.x1 - wo2.posi.x1) + sqr(wo1.posi.x2 - wo2.posi.x2) < sqr(wo1.radius + wo2.radius);
  end;
var
  tvec: TVector2d;
begin
  if checkcollision then
  begin
    tvec := vecscale(1 / (wo1.mass + wo2.mass), vecadd(vecscale(wo1.mass - wo2.mass, wo1.speed), vecscale(2*wo2.mass, wo2.speed)));
    wo2.speed := vecscale(1 / (wo1.mass + wo2.mass), vecadd(vecscale(wo2.mass - wo1.mass, wo2.speed), vecscale(2*wo1.mass, wo1.speed)));
    wo1.speed := tvec;
  end;
end;

nun ist das problem, dass es passieren kann, dass 2 objekte ineinander "hängen":
ausblenden Delphi-Quelltext
1:
  sqr(wo1.posi.x1 - wo2.posi.x1) + sqr(wo1.posi.x2 - wo2.posi.x2) < sqr(wo1.radius + wo2.radius)					

jetzt muss ich die beiden Objekte auf ihren geschwindigkeitsvektoren soweit wieder zurückschieben, dass das hier gilt:
ausblenden Delphi-Quelltext
1:
  sqr(wo1.posi.x1 - wo2.posi.x1) + sqr(wo1.posi.x2 - wo2.posi.x2) = sqr(wo1.radius + wo2.radius)					

das muss eben auch geschwindigkeitsabhängig passieren um die physikalische korrektheit zu gewährleisten.
das würde auch das ineinanderverketten der objekte bei der zufälligen positionsgenerierung verhindern, da sie beim ersten schritt wieder auseinader "gezogen" werden

nun hab ich jedoch keinen plan wie ich das anstellen soll (natürlich möglichst performant ^^)

vielen dank schonmal ;)
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: Fr 03.03.06 17:22 
Einfachste Lösungdu schiebst sie wirklich künstlich noch ein Stückchen auseinander entlang der abprallrichtung (einfache Vektorgeometrie) oder du baust in dein isCollision? Aufruf vorher noch die Abfrage rein, ob sie schon kollidiert sind

Pseudocode;

if alreadycollided=false and iscollision=true

alreadycollided muss dann in iscollision auf true gesetzt werden und wenn iscollision=false dann kann auch alreadycollidied wieder auf false.
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Fr 03.03.06 17:25 
ja dann würden sie durcheinander durchgehen, danach aber nie wieder kollidieren, dass mit dem verschieben meine ich ja, nur wie und wie weit ^^
Freiberger
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

WIN XP
Delphi 7
BeitragVerfasst: Fr 03.03.06 17:37 
Hallo,

ich hatte mal ein Billard-Spiel programmiert. Das sah ganz gut aus.
Was willst du denn machen ?
Wie kommt es dazu, dass sich die Kugeln überhaupt schneiden ?
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Fr 03.03.06 17:47 
die geschwinddigkeit ist kleiner als der durchmesser der kugel und es wird in 50ms schritten gerechnet, deshalb kann es passieren dass eine kugel zu weit in eine andere hineinschießt, weil die geschwindigkeit nicht immer 1px/zeit ist
Freiberger
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

WIN XP
Delphi 7
BeitragVerfasst: Fr 03.03.06 17:53 
ich habe es zwar damals nicht mit Delphi gemacht, aber das Prinzip ist ja das gleiche :

Bevor du die Kugel verschiebst, prüfe einfach die Collision auf die Ziel-Koordinaten.
Falls eine Collision besteht, bleibt die Kugel liegen.

Bei guter Rechenleistung kannst du auch noch Schritte einteilen :
Du machst eine Schleife zB: von 30 bis 1 in 5'er Schritten absteigend.
Erst prüfst du die Verschiebung auf 30 Pixel.
Bei Collision gehst du auf 25 usw.

Kannst ja mal dein Programm schicken...
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Fr 03.03.06 17:56 
du meinst ich sollte schonmal in die zukunft gucken, aber was bringt mir das ? ich schicks dir mal per pm ^^
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 03.03.06 20:44 
Möchtest du eine Überschneidung unbedingt verhindern? Das "ineinanderhängen" lässt sich nämlich auch vermeiden, ohne, dass man gleich zu kontinuierlicher Kollisionserkennung o.ä. greift (oder was meinst du genau mit ineinanderhängen?). Du musst ein Stoss nur dann berücksichtigen, wenn die Kugeln sich einander annähern.

www.delphi-library.d...mp;highlight=billard (Zeile 169)
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Sa 04.03.06 08:15 
ich habe überlegt, und eigentlich müsste ich die kugeln ja nicht zurücksetzen, sondern die strecke die sie ineinander gefahren sind auf die neuen geschwindigkeiten übertragen und zu dem weg addieren aber das ist zu kompliziert, ich guck mir dein billard programm mal an ;)

du arbeitest ja mit koordinatentransformation, ich weiß nicht wirklich genau was die zeile bewirkt, vielleicht könntest du das irgendwie auf meinen code übertragen:
ausblenden Delphi-Quelltext
1:
//hat sich erledigt, s.u.					


ich finds irgendwie unglaublich, dass deins so perfekt funktioniert Oo


Zuletzt bearbeitet von F34r0fTh3D4rk am Sa 04.03.06 10:38, insgesamt 1-mal bearbeitet
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Sa 04.03.06 09:58 
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:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;
  TVector2d = record
    x1,
    x2: double;
  end;
  TMatrix2x2 = record
    m11, m12,
    m21, m22: double;
  end;
  TWO = record
    speed, posi: TVector2d;
    mass, radius: double;
  end;

var
  Form1: TForm1;
  collirect: TRect;
  objs: array [1..10of TWO;

implementation

{$R *.dfm}

function vecscale(s: double; v: TVector2d): TVector2d;
begin
  result.x1 := s * v.x1;
  result.x2 := s * v.x2;
end;

function vecadd(v1, v2: TVector2d): TVector2d;
begin
  result.x1 := v1.x1 + v2.x1;
  result.x2 := v1.x2 + v2.x2;
end;

procedure wowallcollide(var wo: TWO; walls: TRect);
begin
  if wo.posi.x1 - wo.radius < walls.left then
  begin
    wo.posi.x1 := walls.left + wo.radius;
    wo.speed.x1 := - wo.speed.x1;
  end;
  if wo.posi.x1 + wo.radius > walls.right then
  begin
    wo.posi.x1 := walls.right - wo.radius;
    wo.speed.x1 := - wo.speed.x1;
  end;
  if wo.posi.x2 - wo.radius < walls.top then
  begin
    wo.posi.x2 := walls.Top + wo.radius;
    wo.speed.x2 := - wo.speed.x2;
  end;
  if wo.posi.x2 + wo.radius > walls.bottom then
  begin
    wo.posi.x2 := walls.Bottom - wo.radius;
    wo.speed.x2 := - wo.speed.x2;
  end;
end;

procedure wocollide(var wo1, wo2: TWO);
  function checkcollision: boolean;
  begin
    result := sqr(wo1.posi.x1 - wo2.posi.x1) + sqr(wo1.posi.x2 - wo2.posi.x2) < sqr(wo1.radius + wo2.radius);
  end;
var
  dx, dy, l, vp1, vs1, vp2, vs2, vp1_, vp2_, mtot: double;
  m: TMatrix2x2;
begin
  if checkcollision then
  begin
    dx := wo1.posi.x1 - wo2.posi.x1;
    dy := wo1.posi.x2 - wo2.posi.x2;
    l := sqrt(sqr(dx) + sqr(dy));
    m.m11 := dx / l;
    m.m12 := - dy / l;
    m.m21 := dy / l;
    m.m22 := dx / l;
    vp1 := wo1.speed.x1 * m.m11 + wo1.speed.x2 * - m.m12;
    vs1 := wo1.speed.x1 * - m.m21 + wo1.speed.x2 * m.m22;
    vp2 := wo2.speed.x1 * m.m11 + wo2.speed.x2 * - m.m12;
    vs2 := wo2.speed.x1 * - m.m21 + wo2.speed.x2 * m.m22;

    if vp1-vp2 > 0 then
      exit;

    mtot := wo1.mass + wo2.mass;
    vp1_ := (wo1.mass - wo2.mass) / mtot * vp1 + 2 * wo2.mass / mtot * vp2;
    vp2_ := (wo2.mass - wo1.mass) / mtot * vp2 + 2 * wo1.mass / mtot * vp1;

    wo1.speed.x1 := vp1_ * m.m11 + vs1 * m.m12;
    wo1.speed.x2 := vp1_ * m.m21 + vs1 * m.m22;
    wo2.speed.x1 := vp2_ * m.m11 + vs2 * m.m12;
    wo2.speed.x2 := vp2_ * m.m21 + vs2 * m.m22;
  end;
end;

procedure woMove(var wo: TWO);
begin
  wo.posi.x1 := wo.posi.x1 + (form1.Timer1.interval / 1000) / 10 * wo.speed.x1;
  wo.posi.x2 := wo.posi.x2 + (form1.Timer1.interval / 1000) / 10 * wo.speed.x2;
end;

procedure woDraw(Canvas: TCanvas; wo: TWO);
begin
  Canvas.Ellipse(round(wo.posi.x1 - wo.radius), round(wo.posi.x2 - wo.radius), round(wo.posi.x1 + wo.radius), round(wo.posi.x2 + wo.radius));
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  i, j: integer;
begin
  image1.Picture.Bitmap := nil;
  for i := low(objs) to high(objs) do
    womove(objs[i]);
  for i := low(objs) to high(objs) do
  begin
    for j := i + 1 to high(objs) do
      wocollide(objs[i], objs[j]);
    wowallcollide(objs[i], collirect);
  end;
  for i := low(objs) to high(objs) do
    wodraw(image1.canvas, objs[i]);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
  doublebuffered := true;
  for i := low(objs) to high(objs) do
  with objs[i] do
  begin
    radius := 10 + random(11);
    posi.x1 := random(image1.Width - round(radius)) + radius;
    posi.x2 := random(image1.Height - round(radius)) + radius;
    speed.x1 := random(400);
    speed.x2 := random(400);
    mass := 4/3 * radius * radius * radius * pi;
  end;
  collirect := rect(00, image1.Width, image1.Height);
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  collirect := rect(00, image1.Width, image1.Height);
end;

Initialization
  randomize;

end.

so scheint es zu gehen.
fehlt eigentlich nur noch die reibung, wie mache ich das am besten ?
de.wikipedia.org/wiki/Rollwiderstand <- hilft mir nicht sonderlich weiter :P

was ich in deinem code nicht verstehe:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TKugel.Move;
begin
  X := X + (dt/1000)/SubIterations*FVx; // ms => s
  Y := Y + (dt/1000)/SubIterations*FVy;
end;

was bringen die subiterations ?
warum ist das bei mir so langsam Oo

bringt man alle kugel in eine reihe und schießt eine kugel dagegen, gibt es eine durch das interval provizierte verschiebung, je größer das intervall desto größer die verschiebung, obwohl das laut impulserhaltung garnet sein darf :P
Freiberger
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

WIN XP
Delphi 7
BeitragVerfasst: Sa 04.03.06 10:48 
Guten Morgen,

wenn ich das richtig sehe, werden die Kugeln bei Kollision immer im selben Winkel zurückgestoßen.
Man muß die Rollrichtung und den Auftreff-Winkel umrechnen, um auf die neue Richtung zu kommen...
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Sa 04.03.06 11:13 
nee das scheint jetzt zu stimmen, fehlt noch die reibung
so die geschwindigkeit wird jetzt in m/s angegeben und umgerechnet:
ausblenden 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:
const
  meter = 100// 100 px ^= 1 meter

procedure woMove(var wo: TWO);
begin
  wo.posi.x1 := wo.posi.x1 + (form1.Timer1.interval / 1000) * wo.speed.x1 * meter;
  wo.posi.x2 := wo.posi.x2 + (form1.Timer1.interval / 1000) * wo.speed.x2 * meter;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
  doublebuffered := true;
  for i := low(objs) to high(objs) do
  with objs[i] do
  begin
    radius := 10;
    posi.x1 := random(image1.Width - round(radius)) + radius;
    posi.x2 := random(image1.Height - round(radius)) + radius;
    speed.x1 := random(3);
    speed.x2 := random(3);
    mass := 0.016;
  end;
  collirect := rect(00, image1.Width, image1.Height);
end;

dann kann ich auch die tischgröße und die ballgröße davon abhängig machen, sodass das verhältniss dann stimmt
Freiberger
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

WIN XP
Delphi 7
BeitragVerfasst: Sa 04.03.06 12:08 
ich habe die Winkelberechnung aus meinem anderen Programm gefunden.
Da gibt es die Funktion Atanfull( diffx,diffy ).

Wie kann ich in Delphi den Winkel zwischen 2 Punkten errechnen ???
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Sa 04.03.06 12:13 
ich denke mal du meinst das Skalarprodukt ?
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Sa 04.03.06 12:16 
Bitte eröffne einen neuen Thread wenn du eine Frage hast. Danke.

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
Freiberger
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

WIN XP
Delphi 7
BeitragVerfasst: Sa 04.03.06 12:18 
das was ??? :?:

Ich habe 2 Kugeln. Daraus berechne ich die Differen X und Y den Positionen.
Nun brauche ich eine Funktion, die mir sagt, in welchem Winkel von 0-360 Grad sich
Kugel1 zu Kugel2 befindet...
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Sa 04.03.06 12:19 
Wie ich schon sagte: Bitte für eine Frage einen neuen Thread eröffnen. Danke.

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
Freiberger
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 130

WIN XP
Delphi 7
BeitragVerfasst: Sa 04.03.06 12:24 
warum neu eröffen ?
Ich helfe hier nur, das Problem zu lösen...

Das Programm für die Billard-Berechnung habe ich ja, mir fehlt nur die Funktion in Delphi...
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Sa 04.03.06 12:27 
Du willst doch wissen wie man den Winkel zwischen zwei Punkten berechnet.
Das ist ne Frage, die in einen eigenen Thread gehört.

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Sa 04.03.06 14:12 
das hat sich bei mir jetzt aber erledigt, ich mach mal für die reibungsfrage nen neuen thread auf