Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Andorra 2d Billardspiel in 2d (https://www.delphipraxis.net/153275-andorra-2d-billardspiel-2d.html)

Noobmaster 27. Jul 2010 16:13

Andorra 2d Billardspiel in 2d
 
Hallo Leute!
Habe mich in der letzten Zeit ausgiebiger damit beschäftigt, mein eigenes 2d-Billardspiel zu kriieren. Ein kleines Problem, das ich momentan noch habe, ist die Richtung, in der die Kugel laufen soll.
Zum besseren Verständnis: Ich habe einen Geisterball, der die Position des Mauszeigers einnimmt. Wird jetzt die linke Maustaste geklickt, soll der die Weiße in Richtung des Geisterballs laufen. Mein Lösungsansatz war das ganze mit Hilfe der Steigung zu machen, also m=deltaY/deltaX. Allerdings ist die l#Lösung nicht zufreidenstellend, da zum Beispiel Werte wie 117/118 herauskommen können und ich die Kugel ja nicht um 117 und 118 so schnell bewegen lassen kann. Geplant ist nämlich außerdem, dass die Kugel immer nur so weit läuft, wie die Stoßstärke es erlaubt, also bei 50Stoßstärke soll sie nur 50Pixel laufen.
Ich hoffe, dass ihr mein Problem versteht und mir helfen könnt. Ich benutze Andorra2d als Hilfe.
Danke schonmal!

idefix2 27. Jul 2010 17:53

AW: Andorra 2d Billardspiel in 2d
 
Dazu kommt, dass Du bei deltax=0 rausfliegst. Wie wäre es mit Winkelkoordinaten (grad)?

Aphton 27. Jul 2010 20:57

AW: Andorra 2d Billardspiel in 2d
 
Nur mal als Denkanstoß:
Warum benützt du nicht Vektoren? Hierzu müsstest du zumindest die Grundrechenfunktionen von Vektoren wissen.

Beispielscode:
Delphi-Quellcode:
type
  TPointF = record
    X, Y: Single;
  end;

{...}

var
  weißeKugel: TPointF;
  weißeKugelGEIST: TPointF;

  weißeKugelRichtungsVek: TPointF;
  weißeKugelGeschwindigkeit: Single;

{...}

function PointF(const cX, cY: Single): TPointF;
begin
  with Result do
  begin
    X := cX;
    Y := cY;
  end;
end;

{...}

weißeKugelRichtungsVek := PointF( weißeKugelGEIST.X - weißeKugel.X, weißeKugelGeist.Y - weißeKugel.Y );
weißeKugelGeschwindigkeit := SQRT( SQR(weißeKugelRichtungsVek.X) + SQR(weißeKugelRichtungsVek.Y) );
weißeKugelRichtungsVek.X := weißeKugelRichtungsVek.X / weißeKugelGeschwindigkeit;
weißeKugelRichtungsVek.Y := weißeKugelRichtungsVek.Y / weißeKugelGeschwindigkeit;

{
 - Erläuterung:

   weißeKugelRichtungsVek ist ein auf 1 normierter Vektor (dh. die Länge des Vektors (Pfeiles) beträgt 1)
   weißeKugelGeschwindigkeit ist die Länge des Vektors (also die Länge des Pfeiles)

 - Hinweis:

   Wenn du jetzt zB. die Position des Balles ändern willst, müsstest du halt ca. so vorangehen:
     weißeKugel := PointF( weißeKugel.X + weißeKugelRichtungsVek.X * weißeKugelGeschwindigkeit, weißeKugel.Y + weißeKugelRichtungsVek.Y * weißeKugelGeschwindigkeit );
}

mkinzler 27. Jul 2010 21:08

AW: Andorra 2d Billardspiel in 2d
 
Zudem ist 2D ein Sonderfall von 3D (alles auf einer Ebene). So kannst du spezielle Funktionen von DX/OpenGL verwenden

Noobmaster 28. Jul 2010 08:35

AW: Andorra 2d Billardspiel in 2d
 
Das Problem ist, dass wir in der Schule (Klasse 10) bisher nicht mit Vektoren gearbeitet haben. In Physik zwar schon, aber ich wüsste jetzt nicht, wie ich das auf ein Integer-Koordinatensystem übertragen könnte.
Mit der Vektorrechnung oben kann ich leider nicht besonders viel anfangen, sry.
Was für spezielle Funktionen meinst du denn?
Und inwiefern ist das mit den Winkelkoordinaten zu verstehen?

Noobmaster 28. Jul 2010 16:55

Konkretisierung:
 
Damit ihr mein Problem noch besser verstehen könnt. Ich habe allgemein ja leider nur ein Integer-Koordinatensystem(oder sehe ich das falsch und kann Kommazahlen als Koordinaten benutzen!?). Wenn ich nun einmal die Gerade durch Weiße und Geisterball ziehe, dann kann ich ja einen Steigungswinkel ausrechnen. Ist dieser Winkel zum Beispiel 2°, dann ist der Tangens(=Steigung) ungefähr 349/10000 groß. Ich kann aber die Kugel sich nicht 349pixel nach rechts und 10000pixel nach oben bewegen lassen. Arbeite ich noch ungenauer mit 350/10000 komme ich immerhin über Kürzen auf 7/200, aber darf die Weiße nur 50 Pixel rollen, kann man einfach mit Pytagoras schon sehen, dass die 50 weit überschritten werden. Ich kann aber nicht weiter kürzen, da ich die Kugel nicht um z.b 3,5 oder 1,12345pixel bewegen kann.

jfheins 28. Jul 2010 17:07

AW: Andorra 2d Billardspiel in 2d
 
Du bist nicht auf Integers festgelegt!
Zum Anzeigen ja, schon.
Aber du kannst intern mit Double-Werten rechnen (Gleitkommawerte) und nur zum Anzeigen runden.
Ach und: Beschäftige dich etwas mit Vektoren. Ich weiß, was mna nicht kennt ist erstmal total kompliziert, aber das macht echt vieles einfacher.

Du kannst zum Beispiel die Differenz zwischen den (Ortsvektoren von) der Weißen und dem Geisterball bilden. (Das ist dann ein Vektor) und wenn du sagst "die Länge soll genau 50 sein" dann normierst du den Vektor und nimmst ihn mal 50. Zum Subtrahieren, Multiplizieren und Normieren kannst du dir im Nu kleine Funktionen schreiben und das war's ;)

Noobmaster 28. Jul 2010 20:18

AW: Andorra 2d Billardspiel in 2d
 
Danke für die Antwort, aber was ist ein Ortsvektor? Und das mit dem Runden führt zu Ungenauigkeiten, die nicht behebbar sind! So haben es zumindest meine Erfahrungen gezeigt.
Wie normiert man einen Vektor auf 50? Das mit dem Addieren eines Vektors hab ich auf Wikipedia gefunden. Also besteht der Vektor in meinem Fall aus 2 Zahlen? Aus welchen?

Aphton 28. Jul 2010 20:34

AW: Andorra 2d Billardspiel in 2d
 
Liste der Anhänge anzeigen (Anzahl: 1)
Du stellst die richtigen Fragen am falschen Ort.
Informiere dich erstens darüber - ich nehme an, wegen Einfachheit der Frage, dass du dies noch nicht getan hast / ansonsten sry.
Das Vektoren "ein mal eins" ist echt einfach.

Normieren bedeutet einen Vektor auf die Länge 1 zu bringen. Dh. du rechnest dir mit dem Pythagoras die Länge aus -- x und y hast du gegeben, x und y wertest du wie Katheten in nem Dreieck aus und rechnest dir halt die Hypotenuse (= Vektorlänge) aus.
http://upload.wikimedia.org/wikibook...henuse.svg.png
Die x und y Komponente dividierst du durch den erhaltenen Wert und schon hast du einen normierten Vektor (Hypotenuse = 1)

Dies tust du, um später mit Faktoren arbeiten zu können. Dh wiederum wenn du zb die Länge des Vektors begrenzen willst (zb 50) dann schaust du eben, ob dein Faktor >= 50 ist, falls ja, dann setzt du es auf 50.

In kürze folgt hier ne kleine Demo-Anwendung...
Edit: Sodale, WUPPDI!

MfG

jfheins 28. Jul 2010 21:33

AW: Andorra 2d Billardspiel in 2d
 
Zitat:

Zitat von Noobmaster (Beitrag 1038227)
Danke für die Antwort, aber was ist ein Ortsvektor?

Tja, gute Frage :mrgreen:
ich nehme mal an, dass du dich noch nicht tiefergehend mit Vektoren beschäftigt hast (oder das zumindest nicht verstanden hast, sonst würdest du ja nicht fragen...)
Dann probiere ich das mal kurz zu erklären (denn der Wikipediaartikel ist nicht so super gut für Einsteiger)

Ein Vektor ist eine "Liste" von Zahlen die zusammengehören. Und zwar so eng zusammen dass man mit einer einzelnen Zahl nur wenig anfangen kann.
Beispiel Ortsvektor: Um die Position auf einem Lineal zu beschreiben braucht man nur eine Zahl. Wenn man jetzt aber eine Ebene nimmt (z.B. ein Blatt Papier) dann reicht eine Zahl nicht mehr aus. Man braucht zwei Zahlen. (Ist ja auch ein zweidimensionaler Raum)
Die kann man jetzt "X-Wert" und "Y-Wert" nennen, und man kann jedem Punkt auf dem Blatt einen x und einen y wert zuordnen. Als Beispiel "4cm von links und 8cm von oben"
Diese beiden Zahlen kannst du in einen Vektor zusammenfassen. Damit signalisierst du "Diese beiden Zahlen gehören zusammen. immer."
Das nennt man dann einen Vektor. Oder (da ja ein Ort beschrieben wird) einen Ortsvektor.
Dieser Ortsvektor (hier: (4 8)) gibt dir also die Position des Punkts auf dem Blatt an. Damit kannst du weiterrechnen und alle Möglichen sachen anstellen, aber was wichtig ist: Alle Operationen werden auf beide Zahlen in gleichem Maße angewendet. Du kannst also den Vektor verdoppeln und bekommst (8 16) und danach den Vektor (1 -5) addieren und bekommst (9 11)

Also ein Vektor ist wie eine Liste von zahlen die zusammengehören ;)

Zitat:

Und das mit dem Runden führt zu Ungenauigkeiten, die nicht behebbar sind! So haben es zumindest meine Erfahrungen gezeigt.
Ja, das Runden schon. Deshalb rundest du ja nur bei der Ausgabe und rechnest intern mit den genauen Werten weiter ;)

Noobmaster 29. Jul 2010 10:12

AW: Andorra 2d Billardspiel in 2d
 
Okay, verstanden, das sind ja ganz einfache Ortskoordinaten, wie man sie aus Klasse 5 und 6 kennt. Und was genau heißt das jetzt auf mein Spiel angewendet? Kann mir einer ein Beispiel mit verschiedenen Winkeln, aber gleichem Laufweg der Weißen geben? Gebt mit bitte als Beispiel dann jeweils auch die Positionen von Weiß und Geisterball. Danke schonmal.

jfheins 29. Jul 2010 10:42

AW: Andorra 2d Billardspiel in 2d
 
Gut, also nehmen wir mal an, A bezeichnet die weiße Kugel und B die Geisterkugel. (Beides sind also Vektoren mit je einer X und einer Y Komponente)
Die weiße soll nun in Richtung der Geisterkugel laufen. Dann nehmen wir einfach C = B-A (das ist die Differenz der beiden Vektoren)
Und wenn du möchtest dass der Vektor eine Länge von 50 hat:
D = C/|C| * 50 = C/sqrt(Cx^2+Cy^2) * 50

|C| soll hier die Norm darstellen. Danach ist D ein Vektor, der genau 50 Einheiten lang ist und von der weißen Kugel in Richtung Geisterkugel zeigt.

Noobmaster 29. Jul 2010 12:34

Vektor D
 
Muss ich dann also nur noch schreiben, dass der Vektor A + den Vektor D gerechnet wird und dann bewegt sich die Weiße in die richtige Richtung(Das Ergebnis werde ich aufgrund der Wurzel wohl natürlich runden müssen).
Habe ich das so richtig verstanden?

idefix2 29. Jul 2010 12:40

AW: Andorra 2d Billardspiel in 2d
 
A + k*D, k ist die Entfernung zwischen A und dem Endpunkt der Bewegung.

Noobmaster 29. Jul 2010 12:56

AW: Andorra 2d Billardspiel in 2d
 
Ja, aber wenn ich doch jetzt Ax + Dx und Ay + Dy rechne,dann bewegt sich doch die Weiße entlang des Vektors D, oder?

jfheins 29. Jul 2010 16:57

AW: Andorra 2d Billardspiel in 2d
 
Ja, grundsätzlich schon.

Ich weis jetzt nicht genau wie Andorra2D Bewegungen darstellt (ich vermute mal mit einem Geschwindigkeitsvektor, oder du bekommst einfach nur einen Taktschritt mit einem deltaT parameter und musst das dann selber machen)

Um es nochmal zu präzisieren: Wenn du die weiße Kugel an die Position A+D setzt, dann ist sie von ihrer Ausgangsposition 50 (Pixel?) näher an der Geisterkugel dran. Es kann natürlich auch sein dass die Geisterkugel nur 20 Einheiten weg ist, dann ist die weiße jetzt hinter der Geisterkugel. Suie hat sich halt 50 Einheiten in diese Richtung bewegt.

Noobmaster 29. Jul 2010 17:00

AW: Andorra 2d Billardspiel in 2d
 
Danke, ich glaube, ich krieg das jetzt auf die Reihe. Ich werde es demnächst mal ausprobieren und sollte ich Probleme kriegen, dann melde ich mich wieder.

Noobmaster 1. Aug 2010 09:41

AW: Andorra 2d Billardspiel in 2d
 
Es hat wunderbar funktioniert, danke!

Noobmaster 4. Aug 2010 08:17

Neues Problem
 
Delphi-Quellcode:
                  if Energie > 0 then begin
                     X := X + (XSpeed * TimeGap * Energie * 10);
                     Y := Y + (YSpeed * TimeGap * Energie * 10);
                     //Energie neu berechnen, ACHTUNG bei der Wurzel (wurzel aus -X)
                       if XSpeed * YSpeed <> 0 then Energie := Energie - sqrt(abs(((Xspeed*TimeGap)*(XSpeed*TimeGap)))+abs(((YSpeed*TimeGap)+(YSpeed*TimeGap))))
                       else if (XSpeed=0) and (YSpeed <> 0)then Energie := Energie - abs(YSpeed*TimeGap)
                       else if (YSpeed=0) and (XSpeed <> 0)then Energie := Energie - abs(XSpeed*TimeGap);
Energie ist die Laugenergie der Kugel, die anschließend verringert wird. Die Kugel soll ja nicht ruckartig 100Pixel nach rechts springen, sondern es soll ja eine flüssige Bewegung generiert werden. XSpeed und YSpeed rechne ich über die Vektorenrechnung aus. Irgendwie muss ich aber einen Fehler in dem geposteten Text haben. Ist XSPeed*YSpeed<>0, dann ist der Laufweg soweit ich das beurteilen kann, immer derselbe (oder täusche ich mich?). Ist jedoch YSpeed oder XSpeed = 0, dann läuft die Kugel sehr sehr weit, woraus ich schließe, dass ich entweder im ersten Fall zu viel Energie abziehe oder im zweiten Fall zu wenig. FÜr mich sind beide Rechnungen jedoch schlüssig, schließlich wird im ersten Teil eine Diagonale durchschritten, die ich mit Pythagoras ausrechne und im zweiten Fall kann ich ja den direkten Weg abziehen.
Oder liege ich falsch?

jfheins 4. Aug 2010 09:51

AW: Neues Problem
 
Zitat:

Zitat von Noobmaster (Beitrag 1039411)
FÜr mich sind beide Rechnungen jedoch schlüssig,

Für mich nicht. Was du im Grunde machst (bzw. versuchst) ist:
E := E - Norm(Speed) * TimeGap
Norm(Speed) ist die Norm des Geschwindigkeitsvektors.

Was du wirklich tust: ich habe die lange Formel mal etwas auseinander gefriemelt:
Code:
sqrt(
   abs(
      (
         (Xspeed*TimeGap)
         *
         (XSpeed*TimeGap)
      )
   )
   +
   abs(
      (
         (YSpeed*TimeGap)
         +
         (YSpeed*TimeGap)
      )
   )
)
Fällt dir was auf? Beim YSpeed*TimeGap steht ein Plus. Das gehört da nicht hin. (Zumindest wären deine Formeln konsistenter wenn dort ein * stehen würde)

Den Betrag kannst du übrigens weglassen. Die Fallunterscheidung auch. Sieht dann so aus:
Delphi-Quellcode:
  if Energie > 0 then begin
                     X := X + (XSpeed * TimeGap * Energie * 10);
                     Y := Y + (YSpeed * TimeGap * Energie * 10);
                     //Energie neu berechnen
                        Energie := Energie - sqrt(Xspeed*XSpeed + YSpeed*YSpeed) * TimeGap;
;)

Noobmaster 4. Aug 2010 12:52

AW: Andorra 2d Billardspiel in 2d
 
Danke, manchmal sieht man vor lauter Bäumen den Wald nicht mehr :lol:

Noobmaster 5. Aug 2010 16:36

AW: Andorra 2d Billardspiel in 2d
 
Hi, habe ein neues Problem, aber weil es immer noch mit dem Billardspiel zu tun hat, schreibe ich meine Frage hier hin.
Ich bin bei den Kugelkollisionen angekommen. Das Problem für mich ist jetzt sehr schwer zu beschreiben. Wann eine Kugel von einer anderen getroffen wird brauche ich selber nicht zu bestimmten, das erledigt Andorra2d für mich. Nun ist es aber das Problem, dass die Kugel in Wirklichkeit keine flüssige Bewegung macht, sondern "Sprünge":
Delphi-Quellcode:
                     X := X + (XSpeed * TimeGap * Energie * 10);
                     Y := Y + (YSpeed * TimeGap * Energie * 10);
                     //Energie neu berechnen
                     Energie := Energie - sqrt(Xspeed*XSpeed + YSpeed*YSpeed) * TimeGap;
Maximalwert der Energie ist übrigens 25.
Das heißt, dass eine Kollision erst erkannt wird, wenn die eine Kugel eventuell schon tief in der anderen steckt, aber dann kann ich die neuen Richtungen nicht mehr ausrechnen (Im Normalfall prallt die Weiße im 90° Winkel ab, also läuft entlang der Senkrechten zu der Gerade durch die beiden Kugelmittelpunkten)
Ich hoffe ihr könnt mir helfen. Bisher habe ich im Internet nichts gefunden, was mir das Problem verständlich näher bringen konnte.

igel457 5. Aug 2010 18:23

AW: Andorra 2d Billardspiel in 2d
 
Deshalb solltest du dich in solchen Fällen nicht auf die Kollisionsprüfung von Andorra 2D verlassen, sondern über Vektorgleichungen die möglichen Kollisionspunkte im voraus bestimmen...

Noobmaster 5. Jul 2011 14:44

AW: Andorra 2d Billardspiel in 2d
 
Hallo Leute!

Mein Billardspiel ist vorangeschritten (auch wenn es lange gedauert hat).

Die Kugelkollisionen klappen, genauso wie die Kugel-geradeBanden-Kollisionen.

Allerdings tue ich mich mit den Banden in den Ecklöchern schwer. Diese sind nämlich schiefe Flächen und ich habe keine Ahnung wie ich die Abprallrichtung berechnen soll. Die Banden in den Mittellöchern sind nicht im 45°-Winkel sondern knapp weniger als 90°.

Habe mich schon versucht anders zu informieren

Delphi-Quellcode:
              //Steigung der Normalen zur Bande:
              VekNormale := TVek2d.Create;
              VekNormale.x := 1;
              VekNormale.y := -1 / m[j];

              //Richtungsvektor der Kugel an dem Normalenvektor spiegeln:
              //Spiegeln(w an v) = 2*(v*w)/(v*v)*v-w
              Richtung.x := 2*(VekNormale.x*Richtung.x)/(VekNormale.x*VekNormale.x)*VekNormale.x-Richtung.x;
              Richtung.y := 2*(VekNormale.y*Richtung.y)/(VekNormale.y*VekNormale.y)*VekNormale.y-Richtung.y;
              VekNormale.Destroy;
              VekNormale := nil;
Aber so funktioniert es leider nicht...
Anmerkung: "m" ist ein Array für die Steigungen der Geraden, die das jeweilige Bandenstück beschreiben.

Ich wäre sehr dankbar für eure Hilfe,

Gruß,
Noobmaster

Noobmaster 6. Jul 2011 12:17

Bandenkollision
 
Ich komme wirklich nicht weiter.

http://de.wikipedia.org/wiki/Spiegelungsmatrix

Damit kann ich gar nix anfangen...

Weiß einer die Lösung meines Problems?

Im Prinzip will ich folgendes erreichen:
Den Richtungsvektor v=(x,y) meiner Kugel bei der Kollision mit einer beliebigen Gerade g:y=mx+n so verändern, dass die Kugel mit Einfallswinkel=Ausfallswinkel an der Geraden abprallt.

Noobmaster 6. Jul 2011 14:23

AW: Andorra 2d Billardspiel in 2d
 
Habe nun versucht die Formel von Wikipedia auch umzusetzen, nachdem ich mich wieder mal eingehend mit Vektorrechnung abgemüht habe, aber es funktioniert einfach nicht.

Kann mir bitte einer sagen, wie ich einen sich bewegenden Kreis korrekt von einer gerade g(x)=m*x+n abprallen lasse? Habe bisher noch keine Formel gefunden, die ich verstanden habe.

Sinderion 6. Jul 2011 17:16

AW: Andorra 2d Billardspiel in 2d
 
Liste der Anhänge anzeigen (Anzahl: 1)
Statt der Spiegelungsmatrix solltest du es eher mit einer Rotationsmatrix versuchen.

Grundidee wäre, dass du jede Situation auf eine einfachere zurückführst, indem du das Koordinatensystem entsprechend drehst.
Wenn die Kugel auf eine nicht waagrechte(oder auch senkrechte) gerade fällt, drehst du das Koordinatensystem um eben jenen Winkel, sodass du den einfacheren Fall einer Gerade parallel zur x oder y - Achse hast. Hier die neue Richtung berechnen und anschließend wieder zurückdrehen.

Rotiert werden muss nur die Richtung.

Infos zur Rotation: Drehmatrix

Ich hoffe in der Skizze erkennt man einigermaßen was ich meine (Paint :?)

Noobmaster 7. Jul 2011 09:02

AW: Andorra 2d Billardspiel in 2d
 
Danke für deine Antwort!

Leider funktioniert mein Programm noch nicht so ganz. Hier mein Lösungsansatz:

Delphi-Quellcode:
              VekBande := TVek2d.Create;
              VekBande.x := 1;
              VekBande.y := m[j];

              //Drehwinkel:
              Alpha := VekToWinkelinGrad(VekBande) - VekToWinkelInGrad(Richtung);
              Alpha := DegToRad(Alpha);

              //Neue Richtung:
              Richtung.x := Richtung.x * (cos(Alpha)-sin(Alpha)); //richtige Rechnung???
              Richtung.y := Richtung.y * (sin(Alpha)+cos(Alpha));

              FreeAndNil(VekBande);
Zur Ergänzung noch meine Vektor-To-Winkel Umrechnung:
Delphi-Quellcode:
  function VekToWinkelinGrad(Vektor: TVek2d): Real;
  var
     m: Real;
  begin
     //Umwandlung des Vektors in eine Steigung, m=->y/->x,Sonderfälle beachten!
     if Vektor.x = 0 then
     begin
        if Vektor.y > 0 then Result := 270;
        if Vektor.y < 0 then Result := 90;
     end else
     if Vektor.y = 0 then
     begin
        if Vektor.x > 0 then Result := 0;
        if Vektor.x < 0 then Result := 180;
     end else
     begin
        m := Vektor.y / Vektor.x; //entspricht tan(alpha)
        Result := arctan(m); //Achtung Bogenmaß!
        Result := RadToDeg(Result);
        if Result < 0 then //Negativen Winkel umwandeln in positiven
           Result := 360 + Result;
     end;
  end;
Ich hoffe, ihr könnt mir Helfen und bedanke mich schonmal...

Gruß,

Noobmaster

Noobmaster 7. Jul 2011 09:08

AW: Andorra 2d Billardspiel in 2d
 
Zitat:

Zitat von Sinderion (Beitrag 1110360)
Wenn die Kugel auf eine nicht waagrechte(oder auch senkrechte) gerade fällt, drehst du das Koordinatensystem um eben jenen Winkel, sodass du den einfacheren Fall einer Gerade parallel zur x oder y - Achse hast. Hier die neue Richtung berechnen und anschließend wieder zurückdrehen.

Ich hoffe in der Skizze erkennt man einigermaßen was ich meine (Paint :?)

Ja, die Skizza ist logisch ^^: Einfallswinkel = Ausfallswinkel, Klass6

2. Lösungsansatz. Er sieht vom Ergebnis her besser aus, aber irgendetwas ist noch falsch:
Delphi-Quellcode:
              //Neue Richtung:
              Richtung.y := Richtung.y * (cos(Alpha)-sin(Alpha));
              Richtung.x := Richtung.x * (sin(Alpha)+cos(Alpha));
              Richtung.y := -Richtung.y;
Ich glaube, ich muss den Vektor nochmal drehen oder so, aber ich steh grade total auf'm Schlauch...

Noobmaster 7. Jul 2011 12:34

AW: Andorra 2d Billardspiel in 2d
 
"Bei der passiven Drehung wird das Koordinatensystem gedreht und damit der Vektor mit dem Uhrzeigersinn gedreht. Die Koordinaten des Vektors im gedrehten Koordinatensystem findet man durch Multiplikation mit der Matrix R_alpha^-1:" (Wikipedia)

Ich muss also meinen Vektor "Richtung" mit R_alpha^-1 multiplizieren, oder?

Alpha:
alpha = arctan(Steigung der Geraden) - arctan(Richtung.y/Richtung.x)
stimmt das?

Dann also Richtung*R_alpha^-1.
Ist es richtig, dass R_alpha^-1 = (sin(alpha)+cos(alpha)|cos(alpha)-sin(alpha) ist?

Wenn ich den Vektor dann (hoffentlich richtig?) gedreht habe, dann kann ich die Kugel doch abprallen lassen, indem ich
Richtung.y * (-1) rechne, oder?

Und dann? Bin ich dann fertig oder was fehlt noch genau? Zurückdrehen? Wie?
Wie gesagt, ich weiß einfach nicht, wie ich das hinkriegen soll, die Kugel an der schiefen Gerade richtig abprallen zu lassen...

Memnarch 7. Jul 2011 13:48

AW: Andorra 2d Billardspiel in 2d
 
mh..hab zuhause noch ne unit Math3D liegen, die stammt aus nem Tutorial(hab ich von c++ nach Delphi geported) und beinhaltet Klassen für das erstellen und berechnen von Matrizen. Wenn du einfach den Z-wert gleich lässt bei den 3DVectoren, solltest du die so nutzen können. Vorteil ist halt das alles bereits vorhanden ist ;)

Bei bedarf lad ichs hoch.

MFG
Memnarch

Noobmaster 7. Jul 2011 14:13

AW: Andorra 2d Billardspiel in 2d
 
Vielen vielen Dank für dein Angebot. Beinahe hätte ich es auch wirklich in Anspruch nehmen müssen :-).
Habe jetzt nach stundenlangem Kopfzerbrechen - ganz versteckt - eine anscheinend funktionierende Lösung gefunden:
Delphi-Quellcode:
              //Hilfsvektoren:
              VekNormale     := TVek2d.Create;
              VekNeueRichtung := TVek2d.Create;

              //Normale zur Bande bestimmen = Spiegelachse
              VekNormale.x := cos(arctan(m[j]));
              VekNormale.y := sin(arctan(m[j]));

              //Neue Richtung:
              VekNeueRichtung.x := Richtung.x - 2*(Richtung.x*VekNormale.x + Richtung.y*VekNormale.y) * VekNormale.x;
              VekNeueRichtung.y := Richtung.y - 2*(Richtung.x*VekNormale.x + Richtung.y*VekNormale.y) * VekNormale.y;
              Richtung.x := -VekNeueRichtung.x;
              Richtung.y := -VekNeueRichtung.y;

              FreeAndNil(VekNormale);
              FreeAndNil(VekNeueRichtung);
Wie gesagt, anscheinend funktioniert er und das meiste versteh ich sogar :-D.
Wenn ich mein Projekt fertig gestellt habe, dann poste ich vielleicht mal ein Tutorial dazu, da das Programmieren eines eigenen Billardspiels offensichtlich sehr beliebt ist.

Memnarch 7. Jul 2011 14:18

AW: Andorra 2d Billardspiel in 2d
 
Ich hoffe du machst da noch methoden wie VecToAngle oder RotateVector ;)

Bin mal auf das spiel gespannt :)


MFG
Memnarch

Sinderion 7. Jul 2011 16:27

AW: Andorra 2d Billardspiel in 2d
 
Endlich gefunden, wusste doch dass ich so was auch schon mal programmiert habe:

Ist allerdings etwas umständlich gemacht, da es ursprünglich für Polygone gedacht war und anschließend auf einzelne Linien reduziert wurde (das ganze orientiert sich entfernt am Separating Axis Theorem)
Code ist zwar nicht wunderbar, sollte aber funktionieren.

Funktionen:
E liefert den Einheitsvektor
Invert den Normalvektor
Norm den Betrag(=Länge)

Delphi-Quellcode:
function TBall.LineIntersect(const A:TLine):boolean;
var axis,aa,b,vquer:TVector;
p_poly:array[0..1]of extended;
p_circle,M11,M22,M12,M21,pmin,pmax,winkel:extended;
begin
  result := false;
  //Projektion berechnen
  axis := E(Invert(A.Coords[1] - A.Coords[0]));
  p_poly[0] := axis * A.Coords[0];
  p_circle := axis * M;
  //keine Überschneidung wenn ...
  if abs(p_circle - p_poly[0]) > r then exit;

  //Projektion berechnen, zweite Achse
  axis := E(A.Coords[1] - A.Coords[0]);
  p_poly[0] := axis * A.Coords[0];
  p_poly[1] := axis * A.Coords[1];
  p_circle := axis * M;
  pmin := min(p_poly[0], p_poly[1]) - r;
  pmax := max(p_poly[0], p_poly[1]) + r;

  //keine Überschneidung wenn ...
  if not((pmin <= p_circle)and(p_circle <= pmax)) then begin
    result := false;
    exit;
  end;

  result := true;
  //ansonsten Kollision ...
  //Drehmatrix berechnen
  //v anpassen
  //zurückdrehen
  b := A.Coords[1] - A.Coords[0];

  aa.x := 1;
  aa.y := 0;

  winkel := aa * b / Norm(aa) / Norm(b);

  M11 := winkel; M21 := sqrt(1 - sqr(winkel));
  M12 := -M21;  M22 := M11;

  vquer.x := v.x * M11 + v.y * M21;
  vquer.y := v.x * M12 + v.y * M22;

  vquer.y := -1 * vquer.y;

//-Matrix mehr oder weniger ...., alpha = -alpha;
  M21 := -M21;
  M12 := -M12;

  v.x := vquer.x * M11 + vquer.y * M21;
  v.y := vquer.x * M12 + vquer.y * M22;
end;

Noobmaster 8. Jul 2011 09:17

AW: Andorra 2d Billardspiel in 2d
 
Danke nochmal für alle Antworten :-)
Zumindest nach vorläufigen Tests funktioniert die Bandenkollision nun. Letzte Anpassungen im Detail (die eher mit der Kollisionsbestimmung zu tun haben) fehlen noch, aber das ist nur noch Bastelarbeit. Dann kommt das Lochen (sehr einfach gestaltet) und dann der Rahmen des Spiels. Das wird mich jetzt eine Weile beschäftigen ;-)

Und wenn ich das alles habe und es funktioniert, dann versuche ich mich zumindest einmal an Effetwirkung (dann werde ich auch die Funktionen VecToAngle etc. schreiben müssen).

Ich hoffe, ich komme durch, ohne euch nochmal belästigen zu müssen :-).

Euer,

Noobmaster


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz