Kollisionsabfrage zwischen Kreis und Rechteck

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Kollisionsabfrage zwischen Kreis und Rechteck

    Hallo Community,

    ich bin gerade dabei ein kleines Spiel unter IOS zu schreiben, ich arbeite mit dem Buch „Spiele entwickeln für iPhone und iPad“ von Patrick Völcker (nur zu empfehlen) . Ich habe

    mich erstmal dagegen entschiedne das SpriteKit zu benutzen. Zur Zeit beschäftige ich mich mit der Kollisionsabfrage zwischen 2 Objekten, einem Kreis und einem Rechteck.

    Die Theorie ist ja eigentlich recht simpel: prüfen ob sich beide Frames überschneiden, anschließend

    prüfen von wo das andere Objekt kommt und letztendlich mit (die Seitenlänge A)^2 + (der Seitenlänge B)^2 < Radius^2 prüfen ob sich der Kreis und das Rechteck berühren.

    In der Praxis hatte ich es bereits auch schon einmal geschafft, jedoch hatte sich da nur der Kreis bewegt, nun bewegen sich beide Objekte, dies sollte ja aber eigentlich keinen Unterschied machen.

    Jedoch funktioniert es nicht, der Ball kollidiert manchmal nur an einer Seite des Rechtecks,

    manchmal erst in der Mitte.

    Den Quellcode bin ich Gefühlt schon 100 mal durchgegangen, doch irgendwie finde ich den Fehler nicht. Es wäre nett wenn sich einer die Zeit nehmen könnte und mir einmal erklären könnte, was ich falsch gemacht habe.


    Quellcode

    1. if (CGRectIntersectsRect(ball.frame, player.frame)) {
    2. if (ball.center.x < player.frame.origin.x) {
    3. if ( (ball.center.x - player.frame.origin.x) * (ball.center.x - player.frame.origin.x) +
    4. (ball.center.y - player.frame.origin.y) * (ball.center.y - player.frame.origin.y) <=
    5. (ball.bounds.size.width/2 * ball.bounds.size.width/2)) {
    6. [self endGame];
    7. }
    8. }
    9. if (ball.center.x < player.frame.origin.x) {
    10. if ( (ball.center.x - player.frame.origin.x) * (ball.center.x - player.frame.origin.x) +
    11. (ball.center.y - (player.frame.origin.y + player.bounds.size.height)) *
    12. (ball.center.y - (player.frame.origin.y + player.bounds.size.height)) <=
    13. (ball.bounds.size.height/2 * ball.bounds.size.height/2)) {
    14. [self endGame];
    15. }
    16. }
    17. else if (ball.center.x > player.frame.origin.x + player.bounds.size.width) {
    18. if ( (ball.center.x - (player.frame.origin.x + player.bounds.size.width)) *
    19. (ball.center.x - (player.frame.origin.x + player.bounds.size.width)) +
    20. (ball.center.y - (player.frame.origin.y + player.bounds.size.height)) *
    21. (ball.center.y - (player.frame.origin.y + player.bounds.size.height)) <=
    22. (ball.bounds.size.width/2 * ball.bounds.size.width/2)){
    23. [self endGame];
    24. }
    25. }
    26. if (ball.center.x > player.frame.origin.x + player.bounds.size.width) {
    27. if ( (ball.center.x - (player.frame.origin.x + player.bounds.size.width)) *
    28. (ball.center.x - (player.frame.origin.x + player.bounds.size.width)) +
    29. (ball.center.y - player.frame.origin.y) * (ball.center.y - player.frame.origin.y) <=
    30. (ball.bounds.size.width/2 * ball.bounds.size.width/2)){
    31. [self endGame];
    32. }
    33. }
    34. else if (
    35. (
    36. (ball.center.x < player.frame.origin.x) ||
    37. (ball.center.x > player.frame.origin.x + 20)
    38. ) && (
    39. (ball.frame.origin.y >= player.frame.origin.y) &&
    40. (ball.frame.origin.y <= player.frame.origin.y + 20)
    41. )
    42. ) {
    43. [self endGame];
    44. }
    45. else {
    46. [self endGame];
    47. }
    Alles anzeigen



    Danke im Voraus
  • Am besten zu fertigst eine Skizze an und vermerkst dort die Punkte, die du für eine Kollisionsabfrage heranziehst.

    Du arbeitest mir "ball.center.x". Die Koordinate ist am weitesten vom Rand eine Kreises entfernt und denkbar ungeeignet für eine Kollisionsabfrage. Bei einem Kreis prüft man den Radius.

    Grüsse
    goto fail;
  • Es gibt ne Menge Wege ne Kollision der beiden Objekte zu prüfen, die du verwendest ist Verlaub gesagt, ziemlich Kraut und Rüben, wenn die aus dem Buch kommt, schmeiß es weg.

    Quellcode

    1. // Prueft auf eine Kollision zwischen einer AABB und einer Bounding-Sphere
    2. // position ist die Position der Bounding-Sphere
    3. static inline bool collissionBetweenAABBAndSphere( const CFXBBox bbox, const float radius, const CFXVector position)
    4. {
    5. // Suche den Punkt der BBox der am naehsten an position liegt
    6. CFXVector r;
    7. if(position.x < bbox.min.x)
    8. {
    9. r.x = bbox.min.x;
    10. }
    11. else if(position.x > bbox.max.x)
    12. {
    13. r.x = bbox.max.x;
    14. }
    15. else
    16. {
    17. r.x = position.x;
    18. }
    19. if(position.y < bbox.min.y)
    20. {
    21. r.y = bbox.min.y;
    22. }
    23. else if(position.y > bbox.max.y)
    24. {
    25. r.y = bbox.max.y;
    26. }
    27. else
    28. {
    29. r.y = position.y;
    30. }
    31. if(position.z < bbox.min.z)
    32. {
    33. r.z = bbox.min.z;
    34. }
    35. else if(position.z > bbox.max.z)
    36. {
    37. r.z = bbox.max.z;
    38. }
    39. else
    40. {
    41. r.z = position.z;
    42. }
    43. // Distanz berechnen
    44. float dx = position.x - r.x;
    45. float dy = position.y - r.y;
    46. float dz = position.z - r.z;
    47. float distance = dx*dx + dy*dy + dz*dz;
    48. return distance < (radius*radius);
    49. }
    Alles anzeigen


    Was ich hier in meinem Beispiel nicht berücksichtigt hab ist die Zeit. Wenn es ganz bescheiden läuft und dein Spiel mir sehr wenigen Frames läuft, kann es passieren, dass eine Kollision schon statt findet und du das aber gar nicht mit bekommen hast, weil sich die beiden (oder eines der beiden) so ruckelig bewegt, dass es in das andere rein "springt".
    In dem Fall muss du die zurück gelegte Strecke des Objektes nehmen und die Punkte auf der Strecke (ist ein Vektor) für die Kollisionsprüfung nehmen.

    Mals dir mal auf und du weißt was ich meine.