# Kollision eines Kreises mit einem 270° Winkel im 2D-Raum



## Java-Jr. (10. Jan 2013)

Hallo,
Falls das hier nicht ganz genau im richtigen Bereich ist, tuts mir leid, aber ich denke eigentlich, dass das bei den Anfängerthemen schon ganz gut reinpasst.....

Also, ich wollte nur mal so um mein LWJGL mal ein bischen anzuwenden ein kleines Pong schreiben und da ist mir das Problem mit der Kollision gekommen. Die Kollisionserkennung ist ja eher einfach, schwieriger ist, bei einer Kollision des (runden) Balles und einer Ecke eines Rechteckes darauf zu reagieren.....
Ich habe da diverse Sachen probiert und es sieht einfach immer unrealistisch aus, und ich hättte schon ganz gerne eine annähernde physikalische Genauigkeit, zumindest genau genug, damit man die Fehler mit dem Auge nicht erkennt .

Also, die Ecke des Schlägers hat eine X-und eine Y-Koordinate, der Ball hat im Mittelpunkt auch eine und natürlich einen Radius und eine Geschwindigkeit, die in Form eines Vektors, also so zum Beispiel [-2,5] angegeben und in jedem Frame zu seiner Position addiert wird (also eigentlich ganz normal).

Ich würde mich sehr über Lösungsansätze freuen, besonders, wenn sie nicht allzuschwer umzusetzen sind, meine momentane Idee (noch nicht implementiert) ist, grob gesagt, mit ganz komplexen Vektorrechnungen auf einen genauen Winkel zu kommen. Das lässt sich unschön implementieren und hat auch keinen physik-Hintergrund, kann also sehr leicht falsch werden.....

Also, danke schonmal


----------



## Marco13 (10. Jan 2013)

Java-Jr. hat gesagt.:


> Die Kollisionserkennung ist ja eher einfach, schwieriger ist, bei einer Kollision [...] darauf zu reagieren.....



Dem ersten Teil würde ich nicht zustimmen, außer wenn er direkt in Relation zum zweiten gesetzt wird  

Für eine "gute" Kollisionsantwort ist aber auch die Frage relevant, WAS genau man bei der Kollisionserkennung erkennt. Was erkennst du? Dass sich der Ball und der Schläger am Ende des Zeitschrittes überschneiden werden? Das wird ein bißchen knapp (und kann natürlich bei schnellen Bewegungen schlicht dazu führen, dass der Ball durch den Schläger fliegt). Oder machst du irgendwas kontinuierliches? Das wäre dann der Fall, wo der erste Teil der obigen Aussage schon nicht mehr stimmen würde... 

Dann wäre noch relevant, was alles modelliert werden soll. Soll der Ball nur abprallen? Ich nehme an, dass sowohl Ball als auch Schläger eine Position und eine Geschwindigkeit haben. Soll die Bewegung des Schlägers die Geschwindigkeit des Balls beeinflussen? Mit Massen, Impuls und allem drum und dran? Soll man dem Ball einen Drall geben können? Und wenn ja, wie hoch ist die Reibung zwischen Ball und Schläger? Du siehst, man kann beliebig weit gehen...

Eine Möglichkeit, die man in Worten recht leicht runterschreibt (und die für eine vollkommen elastische Kollision auch physikalisch nicht abwegig ist) aber deren Implementierung man schon nicht mehr aus dem Ärmel schüttelt: 
- Man berechnet für den anstehenden Zeitschritt den Zeitpunkt t, an dem sich Ball und Schläger berühren
- Man berechnet für diesen Zeitpunkt t die Punkte pB=pS, an denen sich die Objekte berühren
- Man berechnet die Tangentialebene, an der der Ball abprallt (zum Glück ist ein Ball rund, und in diesem Fall ist es nur ein Kreis, d.h. man braucht nur die Linie, die senkrecht auf der Differenz zwischen pB und dem Kreismittelpunkt liegt - ansonsten bräuchte man die Ebene, die senkrecht zu pB-pS steht, was wegen pB=pS etwas tricky ist...). 
- Änderung der Geschwindigkeit gemäß Einfallswinkel=Ausfallswinkel
- Zwischen t und dem Ende des Zeitschrittes bewegt sich der Ball mit der neuen Geschwindigkeit weiter (von seiner Position zum Zeitpunkt t aus) - und natürlich so lange, bis keine weitere Kollision auftritt. 

Da die das 1972 aber vermutlich nicht so aufwändig gemacht haben, gibt es sicher eine vieeeel einfachere Möglichkeit, die die überzeugenden Ergebnisse liefert, die damals die Leute dazu veranlasst hat, für Pong Münzen in Spielhallenautomaten zu werfen.


----------



## Java-Jr. (10. Jan 2013)

Danke erstma, super Antwort, ich hab wohl echt noch etwas zu wenig gesagt, der Ball soll wirklich wie im Original einfach nur abprallen, ohne Geschwindigkeitsverlust, Spin, Reibung......
Meine Kollisionserkennung ist einfach gehalten: bei einer Überlappung gehts los. Auch hier hab ich sehr gerne Tipps, ich weiß selber, dass das nicht genau oder so ist, nur eben einfach. Würdest du den Speed der Komponenten und den Rest, der Zeitlich bedingt ist über die Systemzeit managen? Ist mir nur grade so eingefallen, das wäre Frameraten-Unabhängig und genau.....
Ja, der Schläger hat auch ein Geschwindigkeit, ich denke aber, dass ich das auch selbst hinbekommen hätte, die zu berücksichtigen, wenn der Rest läuft.

Also, bitte mehr Tipps 

MfG, Theo


----------



## DrZoidberg (10. Jan 2013)

Also, wenn es ganz einfach sein soll, so wir im original Spiel, dann brauchst du keine komplizierten Berechnungen.
Die Schläger sind genau senkrecht also der Ball kollidiert, wenn ball.x - ball.radius < linkerSchläger.x oder halt ball.x + ball.radius > rechterSchläger.x.
Die y Komponente der Ballgeschwindigkeit ändert sich bei der Kollision nicht, nur die x Komponente wird negiert. Es sei denn die Geschwindigkeit des Schlägers beeinflusst den Ball. In dem Fall machst du einfach ball.speed.y += schläger.speed.y*faktor. ball.speed.x wird weiterhin einfach nur negiert. Der Ball kann nicht durch den Schläger durch fliegen, da die Bedingung ja lautet (ball.x - ball.radius < linkerSchläger.x). Da ist es egal wie schnell der ist, der kann nicht durchfliegen. Er kann den Schläger überlappen, aber das kannst du einfach ignorieren, da das bei ausreichend hoher Framerate gar nicht auffällt, wenn der Ball den Schläger für eine 60stel Sekunde überlappt.


----------



## Java-Jr. (10. Jan 2013)

Das ist nich ganz korrekt und auch nicht die Antwort auf meine Frage 

1. Ich habe (wie es im Titel steht) die Kollision des Kreises mit einer Ecke des Rechtecks gemeint, nicht mit einer Seite, wie das funktioniert glaube ich schon zu wissen.

2.Der Ball kann den Schläger sehr wohl durchfliegen, nur wie du sagst bei ausreichend hoher Frame-Rate nicht, bei einem Frame-Einbruch kann es durchaus dabei zu Fehlern durch diese "Durchfliegen" kommen, deshalb würde ich auch gern wissen, wie man eine Kollision genau und etwas im Vorraus erkennt.


----------



## Marco13 (10. Jan 2013)

Nun, DrZoidberg hat schon recht: Im Original wurde vermutlich lediglich die Koordinate geprüft, und um die Form der Ecke (und des Balls, abgesehen vom Radius) hat man sich nicht geschert. Der Ball kann dann zwar durch den Schläger fliegen, aber nur EINEN (ggf. sogar "unsichtbaren") Schritt lang, d.h. das ist egal. Und Ecken gibt es nicht. Entweder der Ball prallt ab, oder eben nicht. Vermutlich könnte man damit, wie angedeutet, das ganze SEHR viel einfacher machen, als wenn man versucht, dort irgendwas physikalisches zu machen und die Ecken zu berücksichtigen. (Ich persönlich finde aber, das einzige was so ein Spiel (oder sowas wie Breakout) interessant machen kann, ist, wenn das Abprallverhalten an den Ecken zumindest "anders" ist - es muss ja nicht "echte berechnet" sein...)


----------



## Crian (11. Jan 2013)

Du möchtest erkennen, ob ein Punkt in Inneren (inkl. Kreisrand) eines Kreises liegt?

Ich habe das in einer Anwendung in meiner Kreisklasse so gelöst:


```
/**
     * Ermittelt, ob der übergebene Punkt auf der Kreislinie oder innerhalb
     * davon liegt.
     *
     * @param point
     *            Zu überprüfender Punkt.
     * @return Wahrheitswert.
     */
    public boolean incloses(Point point) {
        double pointX = point.getX();
        double pointY = point.getY();

        double centerX = center.getX();
        double centerY = center.getY();

        /*
         * Falls der Klick außerhalb des umschließenden Quadrats ist, gleich
         * abbrechen:
         */
        if (pointX < centerX-radius || pointX > centerX+radius
                || pointY < centerY-radius || pointY > centerY+radius) {
            return false;
        }

        /* Nach Pythagoras: */
        double dx = pointX - centerX; // Vorzeichen egal, da quadriert wird
        double dy = pointY - centerY; // Vorzeichen egal, da quadriert wird
        if (dx*dx + dy*dy <= radius*radius) {
            return true;
        }
        else {
            return false;
        }
    }
```

Vielleicht hilft es ja.


----------



## Java-Jr. (11. Jan 2013)

Also, danke erstmal 

Marco, ich hab das aber wie im NinjaCave (LWJGL Basics 4 (Timing) | NinjaCave) Tutorial gezeigt schon größtenteils Frame-Unabhängig gemacht, d.h. bei kleineren Frames steigt die geschwindigkeit und bei einem FPS kann das schonmal das halbe Spielfeld pro Frame sein, deshalb kann man auch den Schläger durchfliegen 
Mir geht es hier wirklich darum, herauszubekommen, in welche Richtung der Ball von der Ecke des Schlägers zurückprallt, ich könnte wetten, dass man dazu den Sinus oder Kosinus verwenden sollte......??
Und hast du BITTE eine Idee oder einen Ansatz wie man das 





> das Abprallverhalten an den Ecken zumindest "anders" ist - es muss ja nicht "echte berechnet" sein...)


hinbekommt?


Crian, danke, das hab ich schon so ähnlich gelöst (genauso Pythagoras ):


```
public static float AbstandVon(float[] ballKoordinate, float[] padderKoordinate) {
		float xAbstand = Math.abs(ballKoordinate[0] - padderKoordinate[0]);
		float yAbstand = Math.abs(ballKoordinate[1] - padderKoordinate[1]);
		return (float) Math.pow(Math.pow(xAbstand, 2) + Math.pow(yAbstand, 2), 0.5);
	}
```

Wenn dieser Abstand kleiner als der Radius des Kreises ist, etc....


----------



## Marco13 (11. Jan 2013)

Zum letzten Codestück: Mach' es so wie Crian es geschrieben hat. (Das abs ist überflüssig, das pow ist langsamer als x*x, und wenn man wirklich den Abstand braucht (und nicht wie in Crians Beispiel der quadrierte Abstrand ausreicht) sollte man sqrt statt pow(...,0.5) verwenden)

Zum Rest:... Nunja... sollte man wirklich von dem Fall von 1 FPS ausgehen? Also, wenn das eintritt (z.B. weil man einen schreicklich suboptimalen Pythagoras implementiert hat ) ist das Spiel ohnehin unspielbar. Wenn Der Ball beim 1. Frame in der Mitte des Bildschirms wäre (und sich nach links bewegt) und beim 2. Frame wieder in der Mitte ist (sich aber nach rechts bewegt, weil er links abgeprallt ist) wäre das irritierend...

Das Abprallverhalten an den Ecken: Ich meinte, dass man sich bestimmt was einfaches überlegen kann. Z.B. dass man die Schläger wie ein 

```
__
 /  \
 |  |
 |  |
 |  |
 |  |
 \__/
```
modelliert (auch wenn man ihn dann ggf. anders, d.h. mit richtigen Ecken an den Ecken) zeichnen könnnte!). Wenn der Ball an den senkrechten Stellen | aufprallt, wird er ganz normal zurückgeworfen:
movementX = -movementX. 
Wenn er an der oberen oder unteren Schäge / \ auftrifft, macht man sowas wie
movementX = -movementX / 2;
movementY =  movementY + movementX / 2; // bzw
movementY =  movementY - movementX / 2; // 
je nachdem ob es oben oder unten an der Ecke war (ist nur ein Gedanke, der das ganze VIEL einfacher machen würde, als eine "echte" Berechnung, aber wie sich das dann spielen läßt, ist schwer zu sagen. (Insbesondere müßte man irgendwas machen, um zu verhindern, dass movementX bei jedem Eckentreffer immer kleiner wird...)


----------



## DrZoidberg (11. Jan 2013)

Also der Schläger besteht praktisch aus mehreren Teilen. Eine Senkrechte Linie, zwei waagerechte Linien und zwei Kreise an den Ecken. Also die graphische Darstellung des Schlägers hat da natürlich keine Kreise sondern abgerundete Ecken aber das mathematische Modell hat da Kreise, der Einfachheit wegen.
Nennen wir die beiden Kreise mal k1 und k2.
Dann sieht der Algorithmus ungefähr so aus. (für den linken Schläger)

```
if(ball.collideswith(schlaeger) {
    if(ball.y >= k1.y && ball.y <= k2.y) ball.speed.x = -ball.speed.x;
    else if(ball.x <= k1.x) ball.speed.y = -ball.speed.y //k1.x und k2.x sind immer identisch
    else {  //Kollision mit einem Kreis
        Kreis k = k1;
        if(ball.y > k2.y) k = k2;
        //denk dir eine Linie vom Mittlepunkt des Kreises zum Mittelpunkt des Balls.
        //wir brauchen jetzt den Winkel zwischen dieser Linie und der x Achse
        double w1 = Math.atan2(ball.y-k.y, ball.x-k.x);
        //und den Winkel in dem sich der Ball relativ zur x Achse bewegt
        double w2 = Math.atan2(ball.speed.y, ball.speed.x);
        double einfallswinkel = w2-w1;
        ball.speed.x = -ball.speed.x;
        ball.speed.y = -ball.speed.y;
        ball.speed.rotate(-2*einfallswinkel);
    }
}
```
Und einen Vektor rotiert man so

```
rotate(Vector v, double angle) {
    double sin = Math.sin(angle);
    double cos = Math.cos(angle);
    double newX = v.x*cos - v.y*sin;
    double newY = v.x*sin + v.y*cos;
    v.x = newX; v.y = newY;
}
```

Das ganze lässt sich übrigens auch ohne die Verwendung von Trigonometrie lösen, mit reiner Vektorrechnung.


----------



## Java-Jr. (11. Jan 2013)

Marco13 hat gesagt.:


> Zum letzten Codestück: Mach' es so wie Crian es geschrieben hat. (Das abs ist überflüssig, das pow ist langsamer als x*x, und wenn man wirklich den Abstand braucht (und nicht wie in Crians Beispiel der quadrierte Abstrand ausreicht) sollte man sqrt statt pow(...,0.5) verwenden)



Super, das ist die Art von Tipps die ich wohl auch ziemlich nötig habe :toll:
-Ja ich hatte wohle Angst, dass die Koordinaten ins negative rutschen könnten, deshalb abs, aber da hab ich die wohl mit der x/y Geschwindigkeit verwechelt :bloed:
das mit dem sqrt glaube ich dir jetzt einfach mal so......

So, ich habe eine physikalisch korrekte (denke ich mal.) Anwendung gefunden.
Die hab ich mal aufgemalt, ich bin echt nicht gut mit Paint und es sieht schlimmer aus, als es komplex ist.

http://img213.imageshack.us/img213/2613/pongphysik.png

Legende: 
S - Schläger
M - Mittelpunkt des Balles
T1 - Tangente des Balles im Kollisionspunkt
T2 - Parallele der Tangente T1 durch den Mittelpunkt M
R1 - Ursprügliche Bewegungsrichtung des Mittelpunktes com Ball
R2 - Neue Bewegungsrichtung
alpha - Winkel Zwischen T1 und R1
alpha' - Gleicher Winkel, abgetragen von T2, der ergibt R2

Damit gilt alpha = alpha' Einfallswinkel gleich Ausfallswinkel. Selbst wenn das physikalisch stimmt, wie zur Hölle schaff ich es, das umzusetzen?!


----------



## Marco13 (12. Jan 2013)

Irgendwie ist das Bild gerade irritierend, würde er bei dieser Bewegung nicht schon früher an die Ecke stoßen?


----------



## Java-Jr. (12. Jan 2013)

Marco13 hat gesagt.:


> Irgendwie ist das Bild gerade irritierend, würde er bei dieser Bewegung nicht schon früher an die Ecke stoßen?



Es ist friehändig gezeichnet, stell dir einfach vor, der gezeichnete Ball ist der erste auf R1, der mit dem Schläger kollidiert


----------



## Java-Jr. (12. Jan 2013)

So ich hab mich nochmal umgesehen:

im Tafelwerk steht: cos(alpha) = (a * b) / (|a| * |b|)  wobei a und b die beiden Vektoren sind und alpha der Winkel zwischen ihnen, für den gilt: 0<= alpha <= 180°

Das rechne ich also für die T1 und R1, weiß nur noch nicht, wie ich von denen je einen Vektor bekomme.
Dann rotiere ich die Richtung des Balles, wie es Dr.Zoidberg gezeigt hat und tadaaaa, ganz korrekte Richtung...oder?


----------



## Marco13 (12. Jan 2013)

Was heißt "von denen"? Der Vektor für die Bewegungsrichtung R1 ist schlicht die Geschwindigkeit. Der Vektor für T1 ist der Vektor, der senkrecht auf der Differenz zwischen dem Kreismittelpunkt und dem Berührungspunkt liegt. WAS der Berührungspunkt ist (bzw. wie man ihn ausrechnet) müßte man sich noch überlegen, bzw. man findet sicher VIEELLL im Web dazu. Irgendwie hab' ich ein etwas flaues Gefühl bei dem Versuch, Gedanken dieser Art auf einem Bild basieren zu lassen, das (speziell in bezug auf den Berührungspunkt) "falsch" ist... aus dem Bauch raus würde ich sagen, dass R2 im Bild stimmen könnte (weil der Berührungspunkt wohl eher auf der _Oberseite_ des Schlägers liegen würde), aber ... wenn man dieses "richtige" Ergebnis aus den "falschen" Eingaben bekommt, bedeutet das dann nicht, dass die _Rechnung_ falsch sein muss? Vermutlich müßte ich da jetzt auch mal ausführlicher Websuchen und Zeichnen....


----------



## Java-Jr. (12. Jan 2013)

Ich denke nicht, dass es schwer wäre, den Berührungspunkt (ich denke mal, du meinst jetzt aud der Kreisbahn, der am Schläger ist ja klar ) herauszufinden, das kannst du ja auch selbst ausprobieren:
Du zeichnest den Padder und eine Linie R1, die sich seiner Ecke auf weniger als den Radius des Kreises annähert, der erste Punkt, bei dem der Abstand von R1 zur Ecke des Schlägers <= dem Radius des Kreises ist, ist der Mittelpunkt dann zeichnest du von diesem Punkt aus eine Linie zur Ecke des Schlägers, die muss dann den Kreisbogen im Berührungspunkt schneiden (mir helfen solche schematischen Skizzen immer sehr).

Erklärt das was, oder habe ich die Schwierigkeit nur nicht verstanden?


----------



## Marco13 (12. Jan 2013)

Wenn es nur um die Ecke geht... Ähm. Vielleicht reden wir aneinander vorbei. Ich denke, dass es im angehängten Bild schwierig ist, den Zeitpunkt t=??? der Kollision und die damit verbundenen Roten Punkte zu bestimmen - also vermutlich das, was du als 
"der erste Punkt, bei dem der Abstand von R1 zur Ecke des Schlägers <= dem Radius des Kreises ist"
beschrieben hast. Wenn ein Rechteck und ein Kreis und eine Bewegung des Kreises (und eine Bewegung des Rechtecks!) gegeben sind, wüßte ich nicht, wie man das machen sollte, außer annähernd mit Intervallhalbierung, oder mit vieeeel Mathematik. Aber wie gesagt, man findet dazu sicher viel im Web (habe bisher noch NIX dazu gesucht, vielleicht denke ich auch nur (mal wieder) zu kompliziert  )


----------



## DrZoidberg (12. Jan 2013)

Ich hatte gestern schon geposted wie man die Kollision zweier Kreise berechnet. Der Code benötigt weder den Berührungspunkt, noch den Radius der Kreise. Und da er unabhängig vom Radius ist, funktioniert er auch für Kreise mit dem Radius 0, also Ecken. Alles was du brauchst ist der Vektor vom Ball zur Ecke und den Geschwindigkeitsvektor des Balls. Der Winkel zwischen beiden ist der Einfallswinkel. Dann rotierst du den Geschwindigkeitsvektor einfach um zwei mal Einfallswinkel und kehrst seine Ruchting um. Das ist alles.


----------



## Java-Jr. (12. Jan 2013)

Kann sein Marco, Ich habe ja eine nahezu konstante, in dem Frame, wenn ich rechne exakte Geschwindigkeit für den Ball.
Dann könnte ich zum Beispiel abfragen, ob Kreis und Schläger sich überlappen und dann kann man ja das kleine Stück auf der Bahn des Balls zum Kollisionspunkt zurückrechnen.


----------



## Java-Jr. (12. Jan 2013)

Ok, DANKE, Zoidberg, was Math.atan2() ist werde ich schon rausfinden. Ich hab mir den Code wahrscheinlich gar nicht genug angesehn, um zu sehen, das das schon größtenteils die Lösung ist 

Aber: Marco und ich wollten einfach den Berührungspunkt genau herausfinden, weil man dann von ihm ausgehen könnte (für die weitere Bewegung des Balls) und das ist ein Bisschen genauer, als aus der Überlappung zu starten.

Den Radius braucht man eigentlich wirklich nicht, außer bei der KollisionsERKENNUNG und die ist in deinem Beispiel nicht dabei, deshalb brauchst du keinen Radius.

Dann noch eine Frage: das Ball/Kreis.y/x in deinem Beispiel ist das die y/x-Koordinate der oberen Ecke des Rechtecks um das jeweilige Element oder des Mittelpunktes?


----------



## DrZoidberg (12. Jan 2013)

Das ist jeweils der Mittelpunkt. Also wenn du abgerundete Ecken an deinem Schläger hast wäre das der Mittelpunkt der Rundung. Bei nicht abgerundeten Ecken wäre es genau die Ecke. Du kannst dir die Ecke eines Rechtecks einfach als Kreis vorstellen, der auch einen Radius von 0 haben kann.
Und Math.atan2(y,x) berechnet den Winkel zwischen einem Vektor und der x Achse.
Den Berührungspunkt kannst du am einfachsten über eine binäre Suche finden.
Das geht so

```
if(ball.collidesWith(Schlaeger)) {
    Vector high = ball.pos;
    Vector low = ball.pos - ball.speed;
    while(length(high - low) > 0.001) {
        Vector middle = (high + low)/2;
        ball.pos = middle;
        if(ball.collidesWith(Schlaeger)) {
            high = middle;
        } else {
            low = middle;
        }
    }
    Vector ballPositionAtCollision = low;
}
```
Also ballPositionAtCollision ist dann die genaue Position, die der Ball zum Zeitpunkt der Kollision hat. Daraus müsste sich der Berührungspunkt dann leicht ermitteln lassen.


----------



## Spacerat (12. Jan 2013)

Also für das ehrwürdige Ur-Pong reichte ein "<Rectangle>.intersects()" für Kollisionsabfragen vollkommen aus, zumal der Ball ja nicht rund war. Für einen runden Ball müsste man nun Aufgrund seines Radiusses sämtliche Punkte seines Umfangs mit "<Rectangle>.contains(point)" überprüfen. Da das aber zu viel Rechnerei ergeben würde, könnte man auch ein BitSet als "Hitbox" verwenden in welchen die Punkte des Balls mit true und die Punkte des Hintergrunds mit false stehen. Wenn dann "<Rectangle>.intersects()" zutrifft, prüft man, ob im Bereich "<Rectangle>.intersection()" der Hitbox ein true auftaucht. Ist dies der Fall, liegt eine Kollision vor. Das Ganze kann man auch für "FutureFrames" machen, sollte aber für Pong nicht nötig sein.
[EDIT]Wenn der Schläger auch abgerundet ist, wird für diesen natürlich auch 'ne Hitbox benötigt.[/EDIT]
[EDIT]...und wer ganz Clever ist, verwendet als Hitbox den Alpha-Kanal der Bilder (z.B. Alpha < 128 bedeutet Hintergrund, Alpha >= 128 bedeutet sichtbar).[/EDIT]


----------



## Java-Jr. (12. Jan 2013)

Sooooo, ich denke mal, das wars also, DANKE!

Noch eine kleine Frage, bevor ich das hier als erledigt markiere: ist es schöner/performanter, was auch immer, ein Array für [x,y] Vektoren oder einen Vektor aus irgendeiner Bibliothek?


----------



## DrZoidberg (12. Jan 2013)

Wieso ein Array? Ich würde da eine Vektor Klasse erstellen.
Sieh dir mal das Programm hier an.
[Java] ball collision - Pastebin.com
Du kannst Bälle ins Spiel bringen indem du mit der Maus klickst, den Mauszeiger in die Richtung bewegst in der sich der Ball bewegen soll und dann loslässt. Verwendet übrigens einen anderen Kollisionsalgorithmus, der auf Vektorrechnung beruht und universeller einsetzbar ist.


----------



## Marco13 (13. Jan 2013)

DrZoidberg hat gesagt.:


> Ich hatte gestern schon geposted wie man die Kollision zweier Kreise berechnet



Der eine Kreis ist aber _bewegt_, und das andere ist evtl. keine Ecke, sondern eine Kante. Es ist nicht so einfach. Aber natürlich kann jeder erst die vermeintlich einfachen Lösungen durchprobieren, das steht jedem frei. (Danach kommt man z.B. bei der binären Suche an, was im Vergleich zu einer analytischen Lösung natürlich auch noch _relativ_ einfach ist)


----------



## DrZoidberg (13. Jan 2013)

Also der Code, den ich am Freitag geposted habe, funktioniert nur wenn einer der beiden Kreise unbeweglich ist, der andere - der Ball - kann aber beweglich sein. Und der unbewegliche Kreis kann beliebig klein sein also z.B. auch eine Ecke mit Radius 0. Und natürlich muss man erst überprüfen, ob der Ball mit einer Ecke oder mit einer Kante kollidiert. Also ich verstehe nicht wo du da ein Problem siehst. Und was hast du gegen Einfachheit? Ich sehe keinen Sinn darin Dinge künstlich zu verkomplizieren.


----------



## Java-Jr. (13. Jan 2013)

Wenn sich der Schläger in Richtung der Kollisions-Ecke bewegt, würde ich irgendwie die Differenz seiner Geschwindigkeit von  der x-Geschindigkeit des Balls zu beiden Geschwindigkeiten des Balls addieren, aber so, dass sie ihr Verhältnis, also die eigentliche Richtung beibehalten....


----------



## Marco13 (13. Jan 2013)

Java-Jr. hat gesagt.:


> Wenn sich der Schläger in Richtung der Kollisions-Ecke bewegt, würde ich irgendwie die Differenz seiner Geschwindigkeit von  der x-Geschindigkeit des Balls zu beiden Geschwindigkeiten des Balls addieren, aber so, dass sie ihr Verhältnis, also die eigentliche Richtung beibehalten....



Ja, das kann man so machen. Bewegung ist so ziemlich das relativste, was es gibt 


@DrZoidberg: Wie gesagt, die Option der binären Suche besteht praktisch immer, und macht das ganze sehr leicht, aber ggf. ineffizient und ungebau im Vergleich zu einer analytischen Lösung. Die Binäre Suche würde aber die Frage "Kante oder Ecke?" relativ leicht mitbehandeln können, deswegen ist das hier vermutlich die geeignetste Wahl.


----------



## Java-Jr. (14. Jan 2013)

Also, ich hab das jetzt so gemacht:


```
float tangente = (float) Math.atan2(-(ball.Y - padder.Y), ball.X -padder.X + padder.width ); //Tangente zum Kollisionspunkt (muss orthogonal zum radius des Kreises, der dahin geht sein, deshalb von diesem Radius die x/y vertauscht und eins von beiden minus genommen.
			float richtung = (float) Math.atan2(ball.Speed[0], ball.Speed[1]);
			
			float alpha = Math.abs(tangente-richtung); //berechnet den Einfallswinkel
			
			rotate(ball.Speed, tangente + alpha); // rotiert um den Einfallswinkel augehend von der Tangente, von der der Ball ja "gedacht" abprallt
```

Aber das funktioniert überhaupt nicht gut.
Zoidberg, deine Kollisions-Reaktion hat auch nicht sehr realistisch ausgesehen..... Ich weiß auch wirklich nicht genau,in was für einer Einheit diese Math.atan2() den Winkel ausgibt, Grad ist das nicht, aber wie ein korrektes Bogenmaß siehts hier auch nicht aus.... 
Exploring Math.atan2( y, x )


----------



## DrZoidberg (15. Jan 2013)

Der Code, den du da verwendet hast ist ja auch völlig anders als meiner.
Teste mal das Programm hier
[Java] Java Pong - Pastebin.com
Verwendet genau den Algorithmus, den ich dir vorgeschlagen hatte. Und das Abprallverhalten an der Ecke scheint mir realistisch zu sein.

Alle Methoden in Math verwenden standardmässig rad für Winkel.
Bsp.

```
double grad = 30;
double rad = Math.toRadians(grad);
double x = Math.cos(rad);
double y = Math.sin(rad);
System.out.println(Math.toDegrees(Math.atan2(y,x)));
[/Java]
Ausgabe:
29.999999999999993
```


----------

