Autor Beitrag
beastofchaos
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 247
Erhaltene Danke: 4



BeitragVerfasst: Di 01.03.11 14:54 
Hallo Leute,
Ich bin Thomas ( 15 Jahre alt ). Hab schon einige Fragen hier gestellt und hab imemr tolle Antworten bekommen. Vll kann mir wieder so erfolgreich geholfen werden.
Also wie der Titel schon sagt, arbeite ich an einem Minigolfprogramm. Ich bin schon so gut wie fertig, doch das wichtigste ist ja, dass das Programm immer wieder bei der neuen Position der Kugel ( in einer Bewegung ) prüft, ob sie ein Hindernis trifft.
Bisher hab ich nur mit dem Mittelpunkt und der Geschwindigkeit gearbeitet - das heißt, dass die Kugel manchmal fast zur Hälfte "im Hindernis" drin war, da er immer nur eine Collision zwischen dem Vektor Mittelpunkt-Geschwindigkeit und dem Hindernis ( in Linien unterteilt als Vektoren mit Ortsvektoren p und Richtungsvektoren r ) geprüft hat.
Nun will ich diesen kleinen Fehler beheben und habe mich mal dran gemacht, dass eine Collision zwischen Kugel und Hindernis geprüft wird. In meinem "Timer" ( ich benutze IdleHandler -> zuverlässiger ) sah das bisher so aus:

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:
27:
28:
TVector2D = record
  x,y: extended;
  end;

TLine = record
  p, r: TVector2D;
  end;

.
.
.

procedure TMainForm.IdleHandler(Sender: TObject; var Done: Boolean);
begin
.
.
.
(* tmp := Kugelgeschwindigkeit*timestep *)
(* lines sind die Linien aller Hindernis in einem Array *)

for i := 1 to high(lines) do
    if LineLineCollision(lines[i], tmp, p) then
      pixel.r := Reflect(tmp, to_v2d(-lines[i].r.y, lines[i].r.x));

.
.
.
end;


Inzwischen habe ich die Linien außer den Randlinien in Typen namens TBarricade ( record = a,b,c,d: TLine; ) eingeteilt und das Programm kann schon prüfen, ob die Kugel sich schneidet mit dem Hindernis, aber wie die Reflektion funktionieren soll, ist immer noch fraglich.

Wenn er auf eine normale Linie trifft benutz ich die selbe Funktion wie schon im vorherigen Quelltext und reflektiere einfach den Geschwindigkeitsvektor ( function Reflect(A, B: TVector2D): TVector2D; ), aber, wenn aber auf eine Kante trifft, könnte es sein, dass er sich an den beiden anliegenden Linien spiegelt und somit einfach in die andere Richtung rollt( die beiden Linien liegen rechtwinklig zu einander ) oder spielt verrückt. Hab ihr shcon mal in der Schule der woanders über die Reflektion einer Kugel an einem Hindernis ( hier Viereck ) nachgedacht? Im Anhang ein kleines Bild fürs Verständnis.

MfG Thomas

PS: es mag nciht sooo viel mit Delphi zu tun haben, aber man braucht in vielen Spielen Vektorenrechnung und entsprechende Funktionen ( ich sag nur Ping Pong, Bubble Shooter etc. ), deswegen wäre so etwas schon gut ;)


Moderiert von user profile iconNarses: Topic aus Dateizugriff verschoben am Di 01.03.2011 um 16:36
Einloggen, um Attachments anzusehen!
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: Di 01.03.11 16:53 
Hey,

(erst Bild angucken)
berechne den Schnittpunkt S der beiden Linien. Stelle den ortogonalen Einheitsvektor (a) auf die Gerade, an der gespiegelt werden soll auf. Berechne mit der Hilfe von a den Punkt x1 (x1 = p - a*radius). Dann stellst du mit p und a die Linie durch p und x1 auf und berechnest den Schnittpunkt (x2) mit der Geraden, an der gespiegelt werden soll. Dann stellst du den Vektor zwischen x1 und x2 auf. Wenn dieser Vektor negativ oder 0 ist und x2 auf der Geraden liegt, dann musst die Kugel am Hinderniss abprallen.

€: wenn x2 nicht auf der Geraden liegt, und Gerade(p, x1) kleiner ist als r, dann musst du die Kugel an der Ecke abprallen lassen, wenn Gerade(p, x3) kleinergleich r ist. Spiegelgerade ist die Ortogonale zur Geraden(p, x3)(ist im Bild bischen schief, aber die roten Striche haben nen rechten Winkel ;) ). siehe Bild2.

MfG Bergmann.
Einloggen, um Attachments anzusehen!
_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Di 01.03.11 18:32 
Wenn ich mir das so anschaue, könnte man alle Kollisionen direkt mit der zweiten Methode behandeln. Würde die Unterscheidung sparen und würde bei gleichschweren Kugeln auch Kugel-Kugel-Kollision beinhalten...
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: Di 01.03.11 18:39 
Hey,

stimmt, das bedeutet dann aber auch ein bischen mehr Rechenaufwand für jede Linie. Weil ja das 2. immer noch mit berechnet werden muss. Ich würde es trotzdem trennen. Is ja nur eine kleine if-Abfrage^^

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Di 01.03.11 19:15 
Ich stelle es mir aber eher kompliziert vor, herauszufinden, ob ich die ecke vorher berühre, oder auf die kante pralle. Im prinzip sollte beides aber erst ab SEHR vielen Kugeln ins Gewicht fallen.
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: Di 01.03.11 20:08 
Hey,

warum ist das schwer? Hab doch oben beschrieben wie es geht :?!?:

Mfg Bergmann

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
beastofchaos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 247
Erhaltene Danke: 4



BeitragVerfasst: Di 01.03.11 23:14 
So, ich hab mir das mal durch gelesen und das klingt totaql logisch. Genauso versteh ich auch die Bilder und kanns mir ( grafisch) vorstellen. Bloß 2 Fragen:

-Wie finde ich den Schnittpunkt von zwei Vektoren (hier ist der Schnittpunkt x2 gemeint). Hab das schonmal gemacht, aber mit einem Umweg, in dem ich die Vektoren teilweise in Funktionen umgewandelt habe und dann vieles umstellen musste.

-Und was meinst du mit negativen Vektoren. Soll ich ihn abfragen, ob die neue Position ( also den Vektor dazugerechnet ) hinter der inie leigt und wie soll ich das anstellen, wenn ich keine Ansicht habe ( naja, könnte die vorherige Kugelstelle merken und aus deren Sicht das anschauen ). Das alles immer in einem Computerprogramm mittels Formeln/Funktionen etc. zu schreiben, ist nochmal was ganz anderes. Bisher habe ich zur BallLinienCollision das Schema folgender Webseite versucht: wiki.delphigl.com/in...arating_Axis_Theorem. Leider kann man an manchen Stellen nur schwer eine Formel für das ganze WirumWarum finden.


So, ich muss jetzt schlafen - habe morgen früh Schule. Also bis morgen Nachmittag oder so - freue mich auf neue Antworten

MfG beast alias Thomas
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: Mi 02.03.11 00:07 
Hey,

zu Frage 1: du brauchst hier nicht den Schnittpunkt von 2 Vektoren, sondern den Schnittpunkt der 2 Geraden, die durch jeweils ein Punkt und ein Vektor definiert sind.
f(x) = m*x + n mit Vektor v und Punkt p
m = v.y / v.x
n = p.y - m*p.x
daraus folgt f(x) := (v.y/v.x)*x + p.y - m*p.x als Formel. Damit kannst du dann den Schnittpunkt berechnen.

zu Frage 2: Man kann die Länge eines Vektor berechnen mit Länge = Wurzel(v.x² + v.y²). Aber mir fällt grad auf, dass das nich geht, weil sich die Objekte ja frei auf der Zeichenfläsche drehen können. Aber du kannst ja mit Vektor a verlgeichen. Wenn der Vektor(x1, x2) (ich nenn ihn mal v) in die andere Richtung zeigt, dann ist er sozusagen negativ. Wenn du die beiden normalisierst, und dann -v = a machst, dann kannst du den Vergleich auch mathematisch im Programm lösen. (Aber das Runden nicht gergessen, oder mit IsNull(v-a) rechnen, da wird intern automatisch gerundet.

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
beastofchaos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 247
Erhaltene Danke: 4



BeitragVerfasst: Mi 02.03.11 15:26 
Wie ich vektoren in Funktionen umwandel und von denen dann den Schnittpunkt berechne, weiß ich. Bloß ist mir das zuviel Gekritzel und umstellen, so dass man am Ende gar nicht mehr erkennt, wie man angefangen hat :)
Mein Bruder (13. Klasse Mathe-LK) meinte, man könnte genauso gut, die Scalaren ( z.B. r1 und r2), mit denen man die Vektoren mal nehmen muss, berechnen. Aber leider ist halt beides zu viel Umgestelle. Naja, ich hatte shcon bereits mittels meiner Methode ( Seperating-Axis-Theorem ) das Problem gelöst, ob der Kreis ein Hindernis schneidet. Wenn es trotzdem nach ein paar Versuchen nicht funktionieren sollte, werd ich zu deiner Methode zurückgreifen.


Meine Frage von anfangs an, war ja eigentlich, wie ich die Kugel reflektiere an einer Kante. Du hast mir bisher den Teil erklärt, wie ich prüfe, ob die Position der Kugel das Hindernis schneidet.
Ich muss noch überlegen, wie ich prüfe, ob die Kugel eine Kante trifft ( vll, wenn er 2 Linien gleichzeitig schneiden sollte ), aber wie berechne ich z.B. in deinem zweiten Bild den Austrittsvektor. Den spiegel ich doch nicht einfach an der roten Linie ( vll "Tangente" in dem Fall ).

Grüße Thomas
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: Mi 02.03.11 15:32 
Hey,

doch genau das machst du. Einfach an der roten Linie im 2. Bild spiegeln ;) Aber du darft die Bewegung der Kugel nicht mit dem roten Strich von p zu x3 verwechseln. Die Richtung der Kugel ist die schmale schwarze Linie (steht auch unten dran). Und wenn du diese schwarze Linie an der roten spiegelst, dann hast du doch ein 1a Ergebniss. Die Prüfung ob eine Ecke getroffen wird hab ich doch oben im 2. Teil auch erklärt :? In dem Beitrag steht alles was man benötigt um die Kollision mit allem möglichen zu realisieren, egal ob Gerade, Ecke oder Kugel.

Mfg Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
beastofchaos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 247
Erhaltene Danke: 4



BeitragVerfasst: Mi 02.03.11 20:15 
Vielen Dank. Hab nochmal dein Text vom Anfang gelesen und er schneidet doch eine Ecke, wenn bei zwei Linien ( nur mit rechten Winkel - benutz ich sowieso ) der Punkt x2 in beiden Fällen nicht auf der Linie liegt und die Gerade(p, x1) kleiner als r ist (wieder in beiden Fällen).

Habe dir mal meinen Quelltext kopiert, mit dem ich einen Schnittpunkt von 2 Vektoren berechnen will - es gibt halt nur ziemlich viele Sonderfälle, bei denen ich die Rechnung extra aufstellen muss:

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:
Function Schnittpunkt(A, B: TLine): TVector2D;
begin
if (v2d_length(A.r) = 0or (v2d_length(B.r) = 0then Exit;
  if (v2d_normalize(A.r).x = v2d_normalize(B.r).x) and (v2d_normalize(A.r).y = v2d_normalize(B.r).y) then Exit;

  if (A.r.x=0and (B.r.y=0then
    begin
    result.x := A.p.x;
    result.y := B.p.y;
    end
  else if (A.r.y=0and (B.r.x=0then
    begin
    result.x := B.p.x;
    result.y := A.p.y;
    end

  else if (A.r.x=0then
    begin
    result.x := A.p.x;
    result.y := B.r.y/B.r.x * A.p.x + B.p.y - B.r.y/B.r.x * B.p.x;
    end
  else if (A.r.y=0then
    begin
    result.x := (B.p.y-A.p.y-B.r.y/B.r.x*B.p.x) / ( - B.r.y/B.r.x );
    result.y := A.p.y;
    end

  else if (B.r.x=0then
    begin
    result.x := B.p.x;
    result.y := A.r.y/A.r.x * B.p.x + A.p.y - A.r.y/A.r.x * A.p.x;
    end
  else if (B.r.y=0then
    begin
    result.x := (A.p.y-B.p.y-A.r.y/A.r.x*A.p.x) / ( - A.r.y/A.r.x );
    result.y := B.p.y;
    end

  else
    begin
    result.x := (B.p.y-A.p.y-B.r.y/B.r.x*B.p.x+A.r.y/A.r.x*A.p.x) / (A.r.y/A.r.x - B.r.y/B.r.x);
    result.y := A.r.y/A.r.x * s.x + A.p.y - A.r.y/A.r.x * A.p.x;
    end;
end;




Naja...Hauptsache es funktioniert xD

Grüße Thomas
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: Mi 02.03.11 20:24 
Hey,

bin grad noch unterwegs. Ich guck dann daheim mal (so um 12 rum). Kannst du mal noch die deklaration von TLine posten? Ich nehme an p is ein punkt un r der richtungsvektor, oder?

Mfg Bergmann

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 02.03.11 21:24 
user profile iconBergmann89 hat folgendes geschrieben Zum zitierten Posting springen:
du brauchst hier nicht den Schnittpunkt von 2 Vektoren, sondern den Schnittpunkt der 2 Geraden, die durch jeweils ein Punkt und ein Vektor definiert sind.
f(x) = m*x + n mit Vektor v und Punkt p
m = v.y / v.x
n = p.y - m*p.x
daraus folgt f(x) := (v.y/v.x)*x + p.y - m*p.x als Formel. Damit kannst du dann den Schnittpunkt berechnen.
Stopp; das Tolle an Vektoren ist, dass man sich diese ganzen Spezialfälle sparen kann: sputsoft.com/blog/20...ne-intersection.html

_________________
>λ=
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: Mi 02.03.11 23:43 
Hey,

an ein lineares Gleichungssystem hab ich auch erst gedacht, als ich die Vektoren gesehen hab^^
Also hier ist jetzt die Methode zur Berechnug der Kollision:
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:
//berechnet den Schnittpunkt von 2 Geraden
//@A: 1. Gerade;
//@B: 2. Gerade;
//@Point: Schnittpunkt der Geraden;
//@result: TRUE wenn Berechnung möglich/erfolgreich, sonst FALSE;
function PointOfIntersection(A, B: TLine; var Point: TVector2f): Boolean;
var
  s, t, tmp: Single;
begin
  result := not((IsZero(A.V.x) and IsZero(A.V.y)) or
                (IsZero(B.V.x) and IsZero(B.V.y)));
  //GleichungsSystem aufstellen und Parameter isolieren
  //A = B
  //AP  + s * AV  = BP  + t * BV
  //-----------------------------------------
  //APx + s * AVx = BPx + t * BVx Gleichung 1
  //APy + s * AVy = BPy + t * BVy Gleichung 2
  //-----------------------------------------
  //APx*AVy + s*AVx*AVy = BPx*AVy + t*BVx*AVy
  //APy*AVx + s*AVx*AVy = BPy*AVx + t*BVy*AVx
  //-----------------------------------------
  //APx*AVy - APy*AVx = BPx*AVy - BPy*AVx + t*(BVx*AVy - BVy*AVx)
  //-----------------------------------------
  //t = (APx*AVy - BPx*AVy + BPy*AVx - APy*AVx)/(BVx*AVy - BVy*AVx)
  //-----------------------------------------
  //t = ((APx-BPx)*AVy + (BPy-APy)*AVx)/(BVx*AVy - BVy*AVx)
  if result then
    tmp := (B.V.x*A.V.y - B.V.y*A.V.x);
    if not IsZero(tmp) then
      t := ((A.P.x-B.P.x)*A.V.y + (B.P.y-A.P.y)*A.V.x)/tmp
    else
      result := false;

  //2. Parameter mit Gleichung 1 berechnen
  //APx + s * AVx = BPx + t * BVx
  //-----------------------------
  //s = (BPx + t * BVx - APx)/AVx
  if result then
    if not IsZero(A.V.x) then
      s := (B.P.x + t * B.V.x - A.P.x)/A.V.x
    else
      s := (B.P.y + t*B.V.Y - A.P.y)/A.V.y;

  //Probe mit Gleichung 1 und 2
  //APy + s * AVy = BPy + t * BVy
  if result then
    result :=
      IsZero((A.P.x + s * A.V.x) - (B.P.x + t * B.V.x), 0.001and
      IsZero((A.P.y + s * A.V.y) - (B.P.y + t * B.V.y), 0.001);
      
  if result then begin
    Point.x := A.P.x + s * A.V.x;
    Point.y := A.P.y + s * A.V.y;
  end;
end;

Wenn du das mit den Gleichungssystemen nich richtig verstehst, dann Frag dein Bruder nochma, das sollte er schon zig tausend mal durchgekaut haben. Du kannst aber auch gerne hier fragen ;)

MfG Bergmann.

p.s.: bei mir ist der Richtungsvektor der TLine das V für Vector. Fand ich besser als das R^^

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
beastofchaos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 247
Erhaltene Danke: 4



BeitragVerfasst: Do 03.03.11 16:39 
Klar weiß ich wie das geht und hab heute in der Schule mal mir ein paar minütchen Zeit genommen und das so einfach wie möglich gemacht :)
Und ob V oder R ist eig Jacke wie Hose xD Hab die Typen TLine, TVector2D von jemandem anderen abgeschaut. p steht für Point, aber r... ( Richtungsvektor = Direction vector ??? ) - vll hat er ja mit "deutschen Variablen" gearbeitet.

Hier mal mein Quelltext mit dieser Vorgehensweise:


Vorweg: Ich hab geprüft, ob eine Linie eine Gerade prüft, weil ich bei deinem Collisionsverfahren zum Ermitteln von x2 mit der Geraden -a und der Linie des Hindernis arbeite -> erspart eine Prüfung bei der zweiten "Linien", ob der Faktor zwischen 0 und 1 liegt bzw. man muss diesen gar nicht erst berechnen ;)

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:
function LineStraightCollision(L, S: TLine): Boolean;
var f: extended;
begin
  result := False;

  if (v2d_length(L.r) = 0or (v2d_length(S.r) = 0then Exit;                    // "v2d_length(v: TVector2D): TVector2D" ermittelt die Länge eines Vektors

  if v2d_equal(v2d_normalize(L.r), v2d_normalize(S.r), 6then Exit;              // "v2d_equal(v1, v2: TVector2D): Boolean" prüft, ob die Vektoren parallel zueinander sind ( prüft x- und y-wert auf 6. Stelle )
                                                                                 // "v2d_normalize(v: TVector2D): TVector2D" ermittelt den Einheitsvektor
  if S.r.x = 0 then
    f := (S.p.x - L.p.x) / L.r.x

  else if S.r.y = 0 then
    f := (S.p.y - L.p.y) / L.r.y

  else if L.r.x = 0 then
    f := (S.r.x * (L.p.y - S.p.y) / S.r.y + S.p.x - L.p.x) / (L.r.x - (S.r.x * L.r.y) / S.r.y)
 
  else (*if (L.r.y = 0) oder Normalfall*)
    f := (S.r.y * (L.p.x - S.p.x) / S.r.x + S.p.y - L.p.y) / (L.r.y - (S.r.y * L.r.x) / S.r.x);

  if (f >= 0and (f <= 1then result := True;

end;


(*
- Für den Normalfall oder wenn L.r.y = 0:

I :   L.p.x + f * L.r.x = S.p.x + g * S.r.x
II:   L.p.y + f * L.r.y = S.p.y + g * S.r.y
I²:   g = (L.r.x * f + L.p.x - S.p.x) / S.r.x

I² in II: 
                         L.p.y + f * L.r.y  =  S.p.y + S.r.y * (L.r.x * f + L.p.x - S.p.x) / S.r.x    | - L.p.y; - S.r.y * L.r.x * f / S.r.x
       f * (L.r.y - S.r.y * L.r.x / S.r.x)  =  S.r.y * (L.p.x - S.p.x) / S.r.x + S.p.y - L.p.y        | / (L.r.y - S.r.y * L.r.x / S.r.x)
                                         f  =  (S.r.y * (L.p.x - S.p.x) / S.r.x + S.p.y - L.p.y) / (L.r.y - (S.r.y * L.r.x) / S.r.x)          // Und das ist das gleiche wie in Zeile 19


- Für L.r.x = 0 muss man einfach von Anfang an bei Gleichung II nach g umstellen, in Gleichung I einsetzen und dann f berechnen  -> dann kommt man auf die Rechnung in Zeile 16

- Für S.r.x = 0 fängt man, wie folgt, an:

I :   L.p.x + f * L.r.x = S.p.x + g * S.r.x           // Das "g * S.r.x" löst sich auf, da "S.r.x = 0"
      L.p.x + f * L.r.x = S.p.x 

 ->   f  =  (S.p.x - L.p.x) / L.r.x

- Für S.r.y = 0 fängt man wie gerade eben an (bloß statt Gleichung I nimmt man Gleichung II)

 ->   f  =  (S.p.y - L.p.y) / L.r.y

*)


Wenn man diese Sonderfälle nicht durchkaut, kommt es vor, dass das das Programm an manchen Stellen mal Null rechnet ( was vll zu Fehlern im Ergebnis führt ) oder er sogar durch Null rechnen will, was zum Error führt :/

Ich denke, meine Vorgehensweise ist gut so und ich verstehe sie zum Glück leichter als deine ;)



Grüße, Thomas

PS: Vll findet ihr einen Fehler in meiner Vorgehesenweise und sagt mir Bescheid - mache das jetzt zum 2. Mal heute (1 mal in der Schule auf nem Schmierblatt) und finde, dass die Rechnung 1A ist :))
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: Do 03.03.11 17:10 
Hey,

ich habs jetzt nicht durchgerechnet, aber im Grunde ist dass das selbe wie meine Rechnung oben. Nur mit dem Unterschied, das du die Sonderfälle vorher abfängst. Ich fang nur die Division mit 0 ab und mach ne Probe (mit s und t). So haben wir das damals in der Schule gelernt. Und ich finde das auch einfacher, als voher die ganze If-Abfragen. Aber wenn du damit deiner Methode besser klar kommst, dann nimm lieber die :)
Nur zur Ergänzung: Wenn man bei meiner Rechnung prüfen will, ob sich die beiden Strecken (nicht mit Geraden verwechseln) schneiden/berühren, dann muss man nur prüfen ob 0 <= s <= 1 und (0 <= t <= 1).

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
beastofchaos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 247
Erhaltene Danke: 4



BeitragVerfasst: Do 03.03.11 17:50 
Jep, ich weiß wie das funktioniert ;)

bei dir kann man das ein bisschen logischer gestalten, indem du statt "if result then" einfach nach der ersten Rechnung nur noch mit else-Blöcken weitermachst :))

Hab da mal ne Frage, du willst in deiner Funktion den Punkt auch noch ausgeben( Zeile 52/53 ). Hab das versucht, aber das geht leider nicht - eine funktion kann also wirklich nur einen Wert ausgeben. Um aber bei deinem Collisionsverfahren x2 zu berechnen, müsste man das iwie schaffen.
Hat da jem ne Idee, sonst muss ich dafür auch noch eine Funktion basteln, die im Grunde genommen das selbe ist, bloß am Ende den Vektor ausgibt.

Also:
ausblenden Delphi-Quelltext
1:
2:
if LineStraightCollision(A, B) then
  x2 := LineStraightIntersection(A, B);


Grüße, Thomas


edit: Problem ist gelöst :))

Man muss, um die originale Variable zu verändern in der Funktion ein var davor schreiben, also: function LineStraightCollision(L, S: TLine; var i: TVector2D): Boolean;
Hast du übrigens auch so xD
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: Do 03.03.11 19:11 
Hey,

so wie bei mir oben: function PointOfIntersection(A, B: TLine; var Point: TVector2f): Boolean; ? ;)
Bei dem if result then hab ich das else besusst nicht geschrieben, weil ich dann da viel einrücken hätte müssen, un da sah einfach doof aus un hat sich beschissen lesen lassen ;)

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
beastofchaos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 247
Erhaltene Danke: 4



BeitragVerfasst: Do 03.03.11 19:24 
Hab doch noch eine Frage, hatte mal am Anfang eine function im Internet gefunden, die ich nicht verstehe - muss aber, wenn ich das Spiel vorstelle, alles erklären können.
Könnt ihr verstehen und mir erklären, wie diese funktion arbeitet, denn sie ist um einiges leichter ist, denke ich xD Aber um das zu verstehen, muss man es warsch. gechrieben hat, aber vll ist das ja doch einem bekannt ;)

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:
27:
28:
29:
function LineLineCollision(A, B: TLine): boolean;
var
  D, Ds, s, Dt, t: extended;
begin

  D := A.r.y * B.r.x - A.r.x * B.r.y;
  if D=0 then                                     // Übrigens weiß ich schon: D = 0 wenn die beiden Linien parallel sind
    begin
    result := false;
    exit;
    end;

    Ds := (B.p.y - A.p.y) * B.r.x - (B.p.x - A.p.x) * B.r.y;
  s := Ds / D;
  if (s < 0or (s > 1then
  begin
    result := false;
    exit;
  end;

    Dt := (B.p.y - A.p.y) * A.r.x - (B.p.x - A.p.x) * A.r.y;
  t := Dt / D;
  if (t < 0or (t > 1then
  begin
    result := false;
    exit;
  end;
  result := true;
end;
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Do 03.03.11 19:28 
ohne das genauer angesehen zu haben, sieht das nach Determinanten aus. Ist ein Verfahren zur Lösung von LGS. Dazu in der Formelsammlung mal Cramersche Regel angucken!