| Autor |
Beitrag |
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Fr 03.03.06 16:38
Ich steh grad mal wieder aufm schlauch
ich habe hier meine prozedur für elastische nicht zentrale stöße:
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":
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:
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
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: 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 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: 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
      
Beiträge: 130
WIN XP
Delphi 7
|
Verfasst: 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 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: 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
      
Beiträge: 130
WIN XP
Delphi 7
|
Verfasst: 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 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: 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
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: 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 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: 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:
Delphi-Quelltext
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 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Sa 04.03.06 09:58
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 public 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..10] of 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(0, 0, image1.Width, image1.Height); end;
procedure TForm1.FormResize(Sender: TObject); begin collirect := rect(0, 0, 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
was ich in deinem code nicht verstehe:
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TKugel.Move; begin X := X + (dt/1000)/SubIterations*FVx; 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 
|
|
Freiberger
      
Beiträge: 130
WIN XP
Delphi 7
|
Verfasst: 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 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: 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:
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; 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(0, 0, 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
      
Beiträge: 130
WIN XP
Delphi 7
|
Verfasst: 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 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Sa 04.03.06 12:13
ich denke mal du meinst das Skalarprodukt ?
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: 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
      
Beiträge: 130
WIN XP
Delphi 7
|
Verfasst: 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
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: 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
      
Beiträge: 130
WIN XP
Delphi 7
|
Verfasst: 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
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: 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 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: 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
|
|