Autor Beitrag
ACiDRAiN
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mo 26.03.12 17:29 
Guten Tag liebe Community,
ich bräuchte eure Hilfe bei meinem Ballkollisionsproblem.
Ich hab viele Theorien aufgestellt, wie ich den Verlauf des Balles in x/y-Richtung (abhängig vom Gegenstand, auf den der Ball aufprallt) umkehren kann.
bx und by sind bei diesem Beispiel auch die jeweiligen Koordinaten des Balles, an denen er sich zum genauen Zeitpunkt befindet.
Ich denke auch, dass es bei mir eher ein mathematisches Problem ist, als ein Problem mit Delphi/OpenGL.

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:
procedure TForm1.Ball;
var k1,k2,bx,by: extended;
begin

if (by<=20and (by>=-12and (bx>=-30.5and (bx<=30.5then
 begin
  by:=by+0.005;
  k1:=bx-0.005;
  k2:=by-0.005;
  bx:=bx+0.005;
 end
else if by>=20 then
 begin
   by:=k2;
   end;

if by>=20 then by:=k2;



  glPushMatrix();
  glTranslatef(00, -50);
  glTranslated(bx, by, 0);
  glBegin(GL_QUADS);
    glColor3f(010); glVertex3f(-1,1,-1);  
    glColor3f(010); glVertex3f(-1,-1,-1); 
    glColor3f(010); glVertex3f(1,-1,-1); 
    glColor3f(010); glVertex3f(1,1,-1); 
  glEnd;
  glPopMatrix();
end;



Ich hoffe, dass mein Code für euch verständlich ist.
Kleine Anmerkung: wenn by=20 ist, dann trifft der Ball die obere Bande, die untere trifft er bei by=-12.
bx=30.5 ist das Auftreffen beim rechten Schläger und bx=-30.5 das Auftreffen beim Linken.

EDIT: Da bx und by unbekannt sind, muss ich auf die jeweils kommen um immer 0.005 davon subtrahieren zu können und somit die Richtung umkehren kann. Da kommt wohl Mathematik infrage, die ich nicht sehr gut beherrsche.


Vielen Dank für eure Hilfe.

MfG,
acidrain
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 26.03.12 20:15 
Hey,

ich blick zwar bei deinem Code nicht 100%tig durch, aber an der Theorie ändert sich ja nix. Hier mal der Ablauf, den du programmieren willst/musst:
Der Ball hat eine bestimmte Position P(x,y) und einen Vektor V(x,y) in dessen Richtung er sich bewegt. Die Länge des Vektors defniert die Geschwindigkeit des Balls. Bei jedem neuen Frame musst du nun die neue Position des Balls berechnen und ggf. Prüfen ob er mit irgendeinem Objekt kollidiert ist. Die neue Position des Balls ist P2(x,y) = P(x,y) + V(x,y). (Wenn du das Ganze noch von der Zeit zwischen den Frames abhängig machen willst, musst du den Vektor noch mit der vergangenen Zeit multiplizieren: P2(x,y) = P(x,y) + V(x,y) * deltaTime). Jetzt guckst du, ob zwischen P und P2 ein Objekt liegt, an dem der Ball hätte abprallen müssen. Mal angenommen da war jetzt ne Wand, dann berechnest du den Schnittpunkt S der Geraden durch P und P2 mit der Wand. Anhand der Länge des Vektors P->S (nenn ich mal d1) erkennst du, wie weit sich der Ball in diesem Schritt bewegt hat, bis er abgeprallt ist. Bis dahin muss er sich also noch mit seinem alten Bewegungsvektor bewegen. Nun berechnest du den Vektor den der Ball nach dem abprallen an der Wand hat (da findet man genug bei Wikipedia & Co. und für Wände parallel zur x- bzw. y-Achse drehst du einfach das Vorzeichen um). Wenn der neue Richtungsvektor V2 berechnet ist, muss sich der Ball noch den Rest des Schrittes weiterbewegen, den er eigentlich in der Wand gemacht hätte. Der Abstand den er zurücklegen muss ist d2 = Länge von V - d1. Also muss sich der Ball um d2 Einheiten von S in Richtung des neuen Vektors V2 bewegen: P3 = S + V2 * d2. P3 ist dann der Punkt den der Ball nach der Kollision hat.
Warum ich das so kompliziert mache? Weil du so erstens eine realistische Kollision hast und 2. verhinderst du, das dein Ball durch die Wand durchschlägt. Ich hab auch mal n Pong geschrieben und das nur mit paar if-Abfragen gemacht un bei mir is der Ball bei einer bestimmten Geschwindigkeit immer durch die Wand durchgewandert^^ Klingt am Anfang bisl kompliziert, is aber eigentlich ganz einfach. Hier noch ne Skizze, damit man das Ganze besser versteht:
kollision

€: noch 2 kleine Tipps am Rande:
  • ausblenden Delphi-Quelltext
    1:
    2:
    3:
    4:
    5:
    6:
      
    //Translationen kann man zusammenfassen. Das:
      glTranslatef(00, -50);
      glTranslated(bx, by, 0);
    //wird zu dem:
      glTranslatef(bx, by, -50);

  • glColor muss man nur einmal setzen, das bleibt solange rot, bis du eine andere Farbe festlegst
  • für Anwendungen die nur zweidimensional arbeiten sollte man auch lieber zweidimensional zeichnen. Stichwort glOrtho



MfG Bergmann.
Einloggen, um Attachments anzusehen!
_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Mo 26.03.12 20:31 
Dein Code ist etwas seltsam, z.B. benutzt du lokale Variblen um die Position des Balls zu speichern...das funktioniert so aber nicht.

Probiers mal so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
type TVector=record
  x: real;
  y: real;
end;

var //global
 BPos: TVector; 
 BDir: TVector;


In BPos speicherst du die Position des Balles.
In BDir speicherst du die Geschwindigkeit des Balles.

Also ist klar, trifft der Ball an den rechten Schläger, dann setzt du einfach
ausblenden Delphi-Quelltext
1:
BDir.x := -BDir.x;					


Die Bewegung des Balles machst du dann so:
ausblenden Delphi-Quelltext
1:
2:
BPos.X := BPos.X + BDir.X*t;
BPos.Y := BPos.Y + BDir.Y*t;

Du kannst t=1 setzen erstmal, aber du wirst dann merken, dass das Programm unterschiedlich schnell ist auf verschiedenen Computern (Stichwort Timebased Movement).

Bleibt dir Frage der Kollision. Etwas Mathe:
Angenommen bei y=20 ist die untere Begrenzung, also gibts eine Kollision, wenn
y=20=BPos.Y+BDir.Y*a;

=> a=(20-BPos.Y)/BDir.Y;

Nach Zeit a trifft der Ball also auf diese Bande. Ist a>t, dann gibts diese Runde keine Kollision mit dieser Bande (evtl aber mit einer anderen).

Ist a<t, dann gibt es die Kollision.

Ich hab im Folgenden Stück mal die Kollision mit einer Bande gezeigt, das sollte für deine Zwecke reichen. Im Code ist aber nur die Kollision mit der unteren Bande gezeigt, die restlichen musst du selbst erledigen. Was auch fehlt ist die Berücksichtigung der dicke der Schläger und des Balls. Das wirkt sich alles jeweils auf die Berechnung von HitTime aus und ist mit dem Codegerüst machbar.
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:
30:
procedure TForm1.Ball(t: real);
var HitTime: real; //=a
begin
  //--- 1. Kollisionszeitpunkt für untere Bande ausrechnen

  if BDir.Y<>0 then //Teilen durch 0 nicht möglich
    HitTime:=(20-BPos.Y)/BDir.Y
  else
    HitTime:=-1//ohne Bewegung in y-Richtung wird's niemals eine Kollision geben 

  //---

  //--- 2. Kollision mit unterer Bande durchführen
  if HitTime<t then
    begin
      BDir.Y:=-BDir.Y;
      BPos.Y:=BPos.Y+HitTime*BDir.Y;
      BPos.X:=BPos.X+HitTime*BDir.X;
      Ball(t-HitTime); //rekursiver Aufruf für die restliche Zeit
    end
  //---

  //--- 3. Keine Kollision => Normal weiterbewegen
  else
    begin
      BPos.Y:=BPos.Y+t*BDir.Y;
      BPos.X:=BPos.X+t*BDir.X;
    end;

end;

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)


Zuletzt bearbeitet von Xion am Mo 26.03.12 21:22, insgesamt 3-mal bearbeitet

Für diesen Beitrag haben gedankt: ACiDRAiN
ACiDRAiN Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mo 26.03.12 21:01 
Vielen Dank für deine Hilfe, Xion.
Bei mir wird jetzt ein Problem ausgespuckt. Und zwar meint Delphi bei der Zeile (Ball(t-HitTime);) dass es zuviele Parameter gibt.
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Mo 26.03.12 21:20 
user profile iconXion hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
procedure TForm1.Ball(t: real);					


PS: hab eben noch einen Fehler ausgebessert.

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)

Für diesen Beitrag haben gedankt: ACiDRAiN
ACiDRAiN Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mo 26.03.12 21:36 
Hatte es selber gemerkt, danke.
Ich habe mir das so angeschaut und mit einem Wert von 0.05 ist der ball annehmbar von der Geschwindigkeit und es kommen keine Fehlermeldungen, wie bei dem Wert von 1.
Nun wollte ich noch letztendlich um eine Denkanregung für die andere bande bzw. schläger alles zu ende zu programmieren.
Als ich das für die untere bande geändert habe, dann flog der ball direkt nach unten, ohne einen winkel einzugehen, vor dem programmieren war's genauso, nur dass der halt nach oben ging. Muss ich da noch mit welchen winkeln spielen/diese zufällig machen? Wieso prallt der Ball nicht von der Bande ab, obwohl er diese erreicht? Auf welche Variablen muss ich achten, beim Konfigurieren für die restlichen Kollisionen?

Mit freundlichem Gruß,
acidrain
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Mo 26.03.12 22:14 
user profile iconACiDRAiN hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe mir das so angeschaut und mit einem Wert von 0.05 ist der ball annehmbar von der Geschwindigkeit und es kommen keine Fehlermeldungen, wie bei dem Wert von 1.

Du musst natürlich BPos (Position des Balls) und BDir (Geschwindigkeit des Balls) am Anfang setzen :!: . BDir wäre z.B. die Geschwindigkeit pro Sekunde und t die vergangene Zeit in Sekunden.

user profile iconACiDRAiN hat folgendes geschrieben Zum zitierten Posting springen:
Nun wollte ich noch letztendlich um eine Denkanregung für die andere bande bzw. schläger alles zu ende zu programmieren.
Als ich das für die untere bande geändert habe, dann flog der ball direkt nach unten, ohne einen winkel einzugehen, vor dem programmieren war's genauso, nur dass der halt nach oben ging.

Kannst du mal deinen Code dazu zeigen?

user profile iconACiDRAiN hat folgendes geschrieben Zum zitierten Posting springen:
Muss ich da noch mit welchen winkeln spielen/diese zufällig machen?

Nein, es gibt hier keine Winkel (nur -x, -y) und nichts zufälliges ;)

ausblenden Delphi-Quelltext
1:
    a:=(20-BPos.Y)/BDir.Y					

Bei Y=20 gibts die Kollision. Wenn du also auch bei der oberen Wand eine Kollision machen willst, dann nimmst du einfach bei Y=-20
ausblenden Delphi-Quelltext
1:
    b:=(-20-BPos.Y)/BDir.Y					

Das heißt nach Zeit a triffst du die eine und nach Zeit b die andere Bande.
Die kleinste der Zeiten macht also die Kollision (solange sie nicht negativ ist, also der kleinste positive dieser Werte). Je nachdem welche Zeit eben die kleinste ist, musst du nun den Geschwindigkeitsvektor verändern.

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)

Für diesen Beitrag haben gedankt: ACiDRAiN
ACiDRAiN Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mo 26.03.12 22:24 
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:
procedure TForm1.Ball(t: real);
var Kollision: real; //=a
begin

  //--- 1. Kollisionszeitpunkt für untere Bande ausrechnen

  if BDir.Y<>0 then //Teilen durch 0 nicht möglich
    Kollision:=(20-BPos.Y)/BDir.Y
  else
    BDir.Y:=-t;

  if BallRi.Y<>0 then //Teilen durch 0 nicht möglich
    Kollision:=(-20-BallPos.Y)/BallRi.Y
  else
    BallRi.Y:=-t;

  //---

  //--- 2. Kollision mit unterer Bande durchführen
  if Kollision<t then
    begin
      BDir.Y:=-BDir.Y;
      BPos.Y:=BPos.Y+Kollision*BDir.Y;
      BPos.X:=BPos.X+Kollision*BDir.X;
      t:=t-Kollision; //restliche Zeit
      Ballbewegung(t-Kollision); //rekursiver Aufruf für die restliche Zeit
    end
  //---

  //--- 3. Keine Kollision => Normal weiterbewegen
  else
    begin
      BPos.Y:=BPos.Y+t*BDir.Y;
      BPos.X:=BPos.X+t*BDir.X;
    end;
    end;


Hierbei bewegt sich der Ball dann automatisch nach unten und egal, ob mit oder ohne die neue Kollision, der Ball bleibt an der Wand stehen und macht garnichts mehr.

Vielen Dank im Vorraus,
acidrain
Blup
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 173
Erhaltene Danke: 43



BeitragVerfasst: Di 27.03.12 17:41 
ausblenden Quelltext
1:
2:
3:
4:
t         = die seit der letzten Berechnung vergangene Zeit
Kollision = die Zeit, nach der eine Kollision eingetreten ist oder eintreten würde
BDir      = der aktuelle Geschwindigkeitsvektor (x, y) des Balls
BPos      = die aktuelle Position (x, y) des Balls

Welche Bedeutung haben diese Variablen?
BallRi = ?
BallPos = ?

Wenn die Geschwindigkeit in Richtung y = 0 ist, gibt es keine Kollision.
Warum weist du in diesem Falls der Ballgeschwindigkeit die vergangene Zeit zu?

Vereinfacht nur für die Kollision mit der unteren Bande:
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:
procedure TForm1.Ball(t: real);
var
  Kollision: real;
begin
  //--- 1. Kollisionszeitpunkt für untere Bande ausrechnen
  if BDir.Y > 0 then
    Kollision := (20 - BPos.Y) / BDir.Y
  else
    Kollision := t;

  if Kollision < t then
  begin
    //--- 2. Bis zur Kollision bewegen
    BPos.Y := BPos.Y + Kollision * BDir.Y;
    BPos.X := BPos.X + Kollision * BDir.X;

    //--- 3. Kollision durchführen
    BDir.Y := -BDir.Y;
    t := t - Kollision; //restliche Zeit
  end;

  //--- 4. Normal weiterbewegen
  BPos.Y := BPos.Y + t * BDir.Y;
  BPos.X := BPos.X + t * BDir.X;
end;

Für diesen Beitrag haben gedankt: ACiDRAiN
ACiDRAiN Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 27.03.12 20:01 
Ich hab einfach BPos und BDir umbenannt für's Verständnis.
Komischerweise funktioniert das Programm nicht, wenn ich deine Vereinfachung anwende :/

Ich bin für jede mögliche Hilfe dankbar!

EDIT: hab das auch mal für andere Kollisionen umgesetzt um euch um kontrolle zu bitten :)

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
if BallRi.Y < -20 then
    Kollision := (-20 - BallPos.Y) / BallRi.Y
  else
    Kollision := t;

  if (BallRi.Y > s1) and (BallRi.x > 30.5)  then
    Kollision := (30.5 - BallPos.y) / BallRi.Y
  else
    Kollision := t;

  if (BallRi.Y < s2) and (BallRi.x < -30.5)  then
    Kollision := (-30.5 - BallPos.y) / BallRi.Y
  else
    Kollision := t;


s1 und s2 sind die koordinaten der schläger, die sich ja durch den tastendruck ändern.

Vielen Dank im Vorraus!
acidrain
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Di 27.03.12 22:03 
user profile iconACiDRAiN hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
      t:=t-Kollision; //restliche Zeit					


Diese Zeile muss weg, die hatte ich in meinem Code fälschlicherweise drin.

user profile iconACiDRAiN hat folgendes geschrieben Zum zitierten Posting springen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
if BallRi.Y < -20 then
    Kollision := (-20 - BallPos.Y) / BallRi.Y
  else
    Kollision := t;

Müsste hier nicht > stehen? Dann hast du aber ein Problem, da dies nicht =0 abfängt. Im Wesentlichen brauchst du hier auch nichts groß berücksichtigen, mit if solltest du nur Abfangen, ob die Geschwindigkeit=0 ist (weil sonst gibts einen Fehler). Also if BallRi.Y<>0 then

Bei den Schlägern wäre eigentlich das Auftreffen durch x-Geschwindigkeit sinnvoller, oder? Also

ausblenden Delphi-Quelltext
1:
2:
3:
4:
  if (BallRi.X <> 0)  then
    Kollision := (s1 - BallPos.X) / BallRi.X  //Zeit, bis x=s1-Gerade geschnitten wird
  else
    Kollision := t;

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)

Für diesen Beitrag haben gedankt: ACiDRAiN
ACiDRAiN Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 27.03.12 22:29 
Danke, Xion du bringst mich echt weiter!

Hier nochmal alles:
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:
if (BallRi.y <> 0then
    Kollision := (20 - BallPos.Y) / BallRi.Y
  else
    Kollision := t;

  if (BallRi.Y <> 0then
    Kollision := (-20 - BallPos.Y) / BallRi.Y
  else
    Kollision := t;

  if (BallRi.X <> 0)  then
    Kollision := (s1 - BallPos.X) / BallRi.X
  else
    Kollision := t;

  if (BallRi.X <> 0)  then
    Kollision := (s2 - BallPos.X) / BallRi.X
  else
    Kollision := t;

  if Kollision < t then
  begin
    // Bewegung zur Kollision
    BallPos.Y := BallPos.Y + Kollision * BallRi.Y;
    BallPos.X := BallPos.X + Kollision * BallRi.X;

    // Kollision durchführen
    BallRi.Y := -BallRi.Y;
  end;

  // Normal weiterbewegen
  BallPos.Y := BallPos.Y + t * BallRi.Y;
  BallPos.X := BallPos.X + t * BallRi.X;
  end;


Alles, so wie beschrieben. Der Ball will sich aber nicht bewegen :/
Es kommt eine Art Fehlermeldung: Auf 'Kollision' zugewiesener Wert wird niemals benutzt.
Hast du eine Idee wodran das liegen kann?

Grüße,
Acidrain
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Mi 28.03.12 11:20 
Ah, ok, da fallen mir noch 3 Sachen auf:

:arrow: Du berechnest die Kollision soweit ok imho. Das Problem ist, dass du den Kollisionswert jedesmal überschreibst. Das letzte if verändert IMMER den Kollisionswert, also ist alles was du vorher berechnet hast, eigentlich hinfällig ;)

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:
  Kollision:=1+t; //lieber etwas mehr als t, sonst gibts evtl Probleme wegen Rundungsfehlern
  if (BallRi.y <> 0then
    begin
      Temp := (20 - BallPos.Y) / BallRi.Y;
      if (Temp>=0)and (Temp<Kollision) then
        Kollision:=Temp;
    end;
  
  if (BallRi.Y <> 0then
    begin
      Temp := (-20 - BallPos.Y) / BallRi.Y;
      if (Temp>=0)and (Temp<Kollision) then
        Kollision:=Temp;
    end;  

  if (BallRi.X <> 0)  then
    begin
      Temp:= (s1 - BallPos.X) / BallRi.X;
      if (Temp>=0)and (Temp<Kollision) then
        Kollision:=Temp;
    end;  
  
  if (BallRi.X <> 0)  then
    begin
      Temp:= (s2 - BallPos.X) / BallRi.X;
      if (Temp>=0)and (Temp<Kollision) then
        Kollision:=Temp;
    end;  

 //Jetzt ist in Kollision die ERSTE mögliche Kollision gespeichert

 if Kollision<t then
  ...


:arrow: Du musst dir irgendwo merken, wie die Kollision stattfinden muss. Momentan prallt der Ball immer in Y-Richtung ab, aber das ist natürlich bei dem Schläger falsch.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
  if (BallRi.X <> 0)  then
    begin
      Temp:= (s2 - BallPos.X) / BallRi.X;
      if (Temp>=0)and (Temp<Kollision) then
        begin
          Kollision:=Temp;
          KollisionDir:=1//1 für X, 0 für Y
        end;
    end
  if Kollision < t then
    begin
      // Bewegung zur Kollision
      BallPos.Y := BallPos.Y + Kollision * BallRi.Y;
      BallPos.X := BallPos.X + Kollision * BallRi.X;

      // Kollision durchführen
      if KollisionDir=0 then
        BallRi.Y := -BallRi.Y
      else if KollisionDir=1 then
        BallRi.X := -BallRi.X
   end;



:arrow: Erstmal nicht so wichtig: Bei der Kollision mit dem Schläger musst du die Y-Koordinate vorher abfragen, weil momentan ist der Schläger unendlich groß und man kann nicht verlieren ;)

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)


Zuletzt bearbeitet von Xion am Mi 28.03.12 11:22, insgesamt 1-mal bearbeitet

Für diesen Beitrag haben gedankt: ACiDRAiN
Blup
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 173
Erhaltene Danke: 43



BeitragVerfasst: Mi 28.03.12 11:21 
Das ist keine Fehlermeldung sondern ein freundlicher Hinweis des Kompilers.
Deine Berechnungen in Zeile 1..4 sind überflüssig, da du das Ergebnis nicht auswertest, sondern in Zeile 7 oder 9 auf jeden Fall überschreibst. Das wiederholt sich dann auch noch...

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:
procedure TForm1.Ball(t: real);
type
  TKollisonObjekt = (oKeine, oLinks, oRechts, oOben, oUnten, oS1, oS2);
var
  Kollision: record
    Objekt: TKollisonObjekt;
    Zeit:   real;
  end;
  t2: real;
begin
  // Für jedes Objekt bestimmen ob und wann eine Kollision eintritt.
  // Das Objekt mit der kürzesten Zeitspanne bis zur Kollision auswählen.
  Kollision.Objekt := oKeine;
  Kollision.Zeit   := t;

  // Bande unten
  if BallRi.y < 0 then
  begin
    t2 := (20 - BallPos.Y) / BallRi.Y;
    if t2 < Kollision.Zeit then
    begin
      Kollision.Objekt := oUnten;
      Kollision.Zeit   := t2;
    end;
  end;

  // Bande oben
  if BallRi.y > 0 then 
  begin
    t2 := (-20 - BallPos.Y) / BallRi.Y;
    if t2 < Kollision.Zeit then
    begin
      Kollision.Objekt := oOben;
      Kollision.Zeit   := t2;
    end;
  end;

  // S1
{...usw...}

// Bewegung bis zur Kollision oder komplette Zeitspanne
  BallPos.Y := BallPos.Y + Kollision.Zeit * BallRi.Y;
  BallPos.X := BallPos.X + Kollision.Zeit * BallRi.X;
// Hier auch alle anderen beweglichen Objekte mit Eigengeschwindigeit für Kollision.Zeit bewegen.

  if Kollision.Objekt <> oKeine then
  begin
    // Richtung und Geschwindigkeit auf Grund der Kollision neu bestimmen
    case Kollision.Objekt of
      oUnten, oOben:
        BallRi.Y := -BallRi.Y;
      oLinks, oRechts:
        BallRi.X := -BallRi.X;
{...usw...}
    end;
    // Rekursiver Aufruf mit der verbleibenden Zeitspanne
    Ball(t - Kollision.Zeit);
  end;
end;


Zuletzt bearbeitet von Blup am Mi 28.03.12 17:38, insgesamt 1-mal bearbeitet

Für diesen Beitrag haben gedankt: ACiDRAiN
ACiDRAiN Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mi 28.03.12 17:08 
Xion, was sind denn KollisionDir und Temp für Variablen?
Wie würde das letztendlich aussehen, denn ich komm mit dem ganzen Zeug irgendwie nicht ganz zurecht. Ich kann sowas eher nachvollziehen, wenn es vollständig ist.

Würde mich freuen, wenn du mir dabei helfen könntest.


Blup, wäre das dann vollständig? Ich hab's nämlich genauso versucht, doch es klappt ebenfalls nicht, es kommt eine Fehlermeldung bei der Rekursion, die sagt, dass es zu viele Parameter gibt.

Grüße,
acidrain
Blup
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 173
Erhaltene Danke: 43



BeitragVerfasst: Mi 28.03.12 17:46 
user profile iconACiDRAiN hat folgendes geschrieben Zum zitierten Posting springen:
Blup, wäre das dann vollständig? Ich hab's nämlich genauso versucht, doch es klappt ebenfalls nicht, es kommen Meldungen, wie Kollision sei ein Undefinierter Bezeichner.

Ich habe den kleinen Rechtschreibfehler bei "Kollision" korrigiert.
Der Quelltext lässt sich jetzt so wie er ist kompilieren.
Das hätte dich aber nicht davon abhalten sollen den Programmablauf zu verstehen.

Unten und Oben sollte der Ball schon richtig abprallen.
Die Stellen die du für die Kollision mit weiteren Objekten ergänzen musst sind mit {...} kommentiert.
Ich werde dir sicher kein vollständiges Programm schreiben.

Für diesen Beitrag haben gedankt: ACiDRAiN
ACiDRAiN Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mi 28.03.12 18:23 
EDIT:
Also, Xion. Ich glaub ich hatte ein paar Fehler gefunden, oder bei mir ist was mit OpenGL falsch, denn egal was ich einstelle der Ball geht durch die Bande.

Hier mein Ball:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.Ball;
begin
  glPushMatrix();
  glTranslatef(BallPos.x, BallPos.y, -50);
  glTranslated(BallRi.x, BallRi.y, 0);
  glBegin(GL_QUADS);
    glColor3f(010); glVertex3f(-1,1,-1);   //lo
    glColor3f(010); glVertex3f(-1,-1,-1); //lu
    glColor3f(010); glVertex3f(1,-1,-1); //ru
    glColor3f(010); glVertex3f(1,1,-1);  //ro
  glEnd;
  glPopMatrix();
end;


Entweder ich hab da was falsch, oder ich muss deinen Vorschlag gemäß meinen Bedingungen ändern. Ich sitze auch schon wieder vier Stunden dran, um das hinzukriegen und hab, wie gestern, keinen Fortschritt gemacht.


EDIT2: Ich hab's selbst hingekriegt!!! Ich kann's einfach nicht glauben, dass jemand so inkompetentes, wie ich, endlich mal was in Delphi auf die Reihe kriegt.
Jetzt kommen die Kollisionen der Schläger. Hiermit bedanke ich mich herzlichst für EURE Unterstützung, denn ohne EUCH wäre ich nie so weit gekommen!

Grüße,
acidrain