CGRectIntersectsRect reagiert nicht bzw. falsch

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

  • CGRectIntersectsRect reagiert nicht bzw. falsch

    Hi,

    ich häng jetzt schon etwas länger an einem Problem, ich möchte das ein Bild (Ball) von einem anderen Bild (Loch) wie ein Magnet angezogen wird. So den Code hab ich dafür auch schon so gut wie fertig, nur funktioniert er nicht so wie ich es mir erhofft habe :(
    Auch eingebaut habe ich, dass der Ball nur bis zum Bildschirmrand bewegt werden kann.

    Hier mein Code:

    Quellcode

    1. - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    2. {
    3. CGPoint aktuelleMitte = [[touches anyObject] locationInView:self];
    4. CGPoint neueMitte = CGPointMake(self.center.x + (aktuelleMitte.x - touchPunkt.x),
    5. self.center.y + (aktuelleMitte.y - touchPunkt.y));
    6. float screenMitteX = CGRectGetMidX(self.bounds);
    7. if (neueMitte.x > self.superview.bounds.size.width - screenMitteX)
    8. neueMitte.x = self.superview.bounds.size.width - screenMitteX;
    9. else if (neueMitte.x < screenMitteX)
    10. neueMitte.x = screenMitteX;
    11. float screenMitteY = CGRectGetMidY(self.bounds);
    12. if (neueMitte.y > self.superview.bounds.size.height - screenMitteY)
    13. neueMitte.y = self.superview.bounds.size.height - screenMitteY;
    14. else if (neueMitte.y < screenMitteY)
    15. neueMitte.y = screenMitteY;
    16. self.center = neueMitte;
    17. self.highlighted = YES;
    18. CGRect lochKlein = CGRectInset(loch.frame, +10.0, +10.0);
    19. if (CGRectIntersectsRect (ball.frame, lochKlein )) {
    20. [UIView animateWithDuration:0.1
    21. animations:^{ lernenPlaettchen.center = lernenLoch.center; }];
    22. }
    23. }
    Alles anzeigen



    Wenn ich den Ball in den gewünschten Bereich bewege passiert nichts, sobald ich dann aber (wenn der Ball im gewünschten Bereich ist) auf das Loch drücke und bewege, schnappt der Ball in das Loch wie gewünscht ein 8|

    Ich komm einfach nicht drauf wo mein Fehler liegt :( wäre echt nett wenn mir jemand die Augen öffnen könnte

    MfG Richi
  • Also ohne jetzt Deinen Code durchzulesen. Ne einfache Möglichkeit, Du baust nen Vektor zwischen den beiden Objekten.
    Wenn Du den hast, nimmst Du die Länge des Vektors, wenn die einen gewissen Wert unterschreitet, ist der Ball im Loch.

    Den Ball im Bild zu halten ist auch nicht schwerer, die linke Kante des Balls (X-Wert) kann nie kleiner 0 und nie größer als Bildschirmbreite - Ballbreite sein.
    Genauso gehst Du mit dem Y-Wert vor.
  • MCDan schrieb:

    Aus dem Source Code geht leider nicht hervor welche Werte die size von loch und ball hat. ;)


    Wofür brauche ich denn die Größen ?( ich war der Annahme das es reicht die UIImageView´s in der .h zu deklarieren und mit den richtigen UIImageView´s im Storyboard zu verlinken :|
    Also muss ich erst die Größen ermitteln lassen ? Ich hab aber noch nicht ganz geschnallt was ich dann mit den Größen mache ?(

    wolf_10de schrieb:


    Also ohne jetzt Deinen Code durchzulesen. Ne einfache Möglichkeit, Du baust nen Vektor zwischen den beiden Objekten.
    Wenn Du den hast, nimmst Du die Länge des Vektors, wenn die einen gewissen Wert unterschreitet, ist der Ball im Loch.

    Den Ball im Bild zu halten ist auch nicht schwerer, die linke Kante des Balls (X-Wert) kann nie kleiner 0 und nie größer als Bildschirmbreite - Ballbreite sein.
    Genauso gehst Du mit dem Y-Wert vor.


    Danke für die Antwort aber weil ich grade dabei bin mir das ganze selber etwas beizubringen und ich noch nicht ganz so weit bin kommt mir deine Methode im Moment leider etwas kompliziert vor :huh:
    und ich möchte gerne erfahren wieso es nicht so funktioniert wie ich mir das vorgestellt habe.
  • Ich wollte nur mal prüfen, ob Deine Annahme, wie CGRectInset() funktioniert korrekt ist. Wenn die size von loch und ball <= 20.0 ist, dann wird Deine Abfrage nicht funktionieren, da lochKlein dann eine size von <= 0 hat.

    Daher wollte ich gerne wissen, welche Werte size von loch und ball hat. ;)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von MCDan ()

  • Du brauchst die Größe um eine Überschneidung (RectIntersect) zu ermitteln. Die Größe kannst Du Dir sparen, wenn du den Ansatz nimmst, den ich vorgeschlagen haben, wobei RectIntersect schneller ist, sollte aber bei deinem Beispiel keine Rolle spielen.

    Ich hab hier was kleines zur Kollisionserkennung geschrieben:
    wr-media.net/spaceinvaders.php
  • Richi1987 schrieb:

    Achso 8o ja die sind um einiges Größer, aber leider hilft mir das bis jetzt noch nicht viel weiter :D

    Ist es vlt. noch wichtig zu wissen das ich den Code in einer Klasse geschrieben hab die von UIImageView abstammt?
    Nein was das für eine Klasse ist spielt keine Rolle, die kann auch ein Pfannkuchen sein, wichtig sind 2 Dinge
    1. die Positionen de beiden Objekte
    2. dur Größe der beiden Objekte
  • Kann es sein, dass du beim Bewegen des Balls sowohl den Ball als auch das Loch bekommst, touches damit ein Set mit ungefähr 2 Objekten wird und -anyObject: eher zufällig den Ball zurück gibt?

    Du könntest versuchen, einfach 'Ball' selbst zu bearbeiten statt [touches anyObject];

    C-Quellcode

    1. - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    2. {
    3. if(![touches containsObject:ball])
    4. {
    5. // Ball wurde nicht berührt, Methode kann verlassen werden.
    6. return;
    7. }
    8. // Ball wurde berührt, nehmen wir doch einfach seine aktuellen Daten.
    9. CGPoint aktuelleMitte = [ball locationInView:self];
    10. // ...
    11. }
    Alles anzeigen


    Wobei ich einfach nicht weiß, ob der Ball während touchesMoved: schon eine angepasste -locationInView: hat.
    Vielleicht hat er das ja nicht, und deshalb greift deine Abfrage nicht.

    Eventuell bekommst du über das Event ja die aktuelle Position heraus und nimmst diese für den Mittelpunkt.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Richi1987 schrieb:

    Achso 8o ja die sind um einiges Größer, aber leider hilft mir das bis jetzt noch nicht viel weiter :D

    Ist es vlt. noch wichtig zu wissen das ich den Code in einer Klasse geschrieben hab die von UIImageView abstammt?

    Hm, befinden sich loch und ball überhaupt im selben superview, d.h. sind die frames von ball und loch im selben Korrdinaten-System?

    Gib in der Methode vor der Abfrage mit CGRectIntersectsRect doch einfach mal beide CGRects von ball.frame und lochKlein per:

    Quellcode

    1. NSLog(@"ball.frame=%@\n lochklein=%@",NSStringFromCGRect(ball.frame),NSStringFromCGRect(lochKlein));
    aus.
  • wolf_10de schrieb:

    Es reicht doch vollkommen aus, von beiden Objekten die frame zu holen, da muss man keinen Mittelpunkte mehr ermitteln.

    Wird denn der Frame während des Drags angepasst?
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Lucas de Vil schrieb:

    wolf_10de schrieb:

    Es reicht doch vollkommen aus, von beiden Objekten die frame zu holen, da muss man keinen Mittelpunkte mehr ermitteln.

    Wird denn der Frame während des Drags angepasst?
    edit/ Na davon gehe ich doch aus, wie sonst weiß das System, wo es das Teil hin malen soll? /edit

    noch mal edit/
    bin ich blöd, jetzt weiß ich was Du meinst, ne den frame muss er natürlich selbst aktualisieren, er will den Ball ja bewegen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von wolf_10de ()

  • wolf_10de schrieb:

    Lucas de Vil schrieb:

    wolf_10de schrieb:

    Es reicht doch vollkommen aus, von beiden Objekten die frame zu holen, da muss man keinen Mittelpunkte mehr ermitteln.

    Wird denn der Frame während des Drags angepasst?

    edit/ Na davon gehe ich doch aus, wie sonst weiß das System, wo es das Teil hin malen soll? /edit

    Mein Chef sagt immer: "Du sollst nicht davon ausgehen, dass."

    Das System könnte ein Image des Objektes erzeugen und hin und her draggen. Macht es unter Mac OS ja auch.

    Am Sichersten ist es offenbar wirklich, wenn man über das Event geht:

    C-Quellcode

    1. - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    2. {
    3. if(![touches containsObject:ball])
    4. {
    5. // Ball wurde nicht berührt, Methode kann verlassen werden.
    6. return;
    7. }
    8. // Ball wurde berührt, nehmen wir doch einfach seine aktuellen Daten.
    9. // Wir gehen mal davon aus, dass es irgendwie von UIView erbt.
    10. UIView * touchedView = ball;
    11. NSSet * ballTouches = [event touchesForView:touchedView];
    12. // Obacht: könnten mehrere Touches sein. Ich hoffe mal das nicht...
    13. UITouch * ballTouch = [ballTouches anyObject];
    14. CGPoint currentLocation = [ballTouch locationInView:[touchedView superview]];
    15. CGPoint previousLocation = [ballTouch previousLocationInView:[touchedView superview]];
    16. // ...
    17. }
    Alles anzeigen


    // Nachtrag: und via currentLocation und previousLocation bekommt man dann auch den Bewegungsvektor raus. ^^
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Kann es sein, dass du beim Bewegen des Balls sowohl den Ball als auch das Loch bekommst, touches damit ein Set mit ungefähr 2 Objekten wird und -anyObject: eher zufällig den Ball zurück gibt?

    Ich habe alles auf dem View mit dem Storyboard arrangiert und bei dem UIImageView von Loch habe ich im Attribut-Inspector keinen Haken bei "User Interaction Enabled" daher dachte ich das es eh ignoriert wird.


    Gib in der Methode vor der Abfrage mit CGRectIntersectsRect doch einfach mal beide CGRects von ball.frame und lochKlein per:

    Quellcode
    1
    NSLog(@"ball.frame=%@\n lochklein=%@",NSStringFromCGRect(ball.frame),NSStringFromCGRect(lochKlein));
    aus.

    Die NSLog: gibt das hier aus ich glaube das ist nicht so ganz richtig oder? :D

    ball.frame={{0, 0}, {0, 0}} lochklein={{inf, inf}, {0, 0}}

    //nachtrag: ich bin verwirrt :wacko:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Richi1987 ()

  • So, habs kurz getestet, Kollision zwischen den beiden Objekten:

    Quellcode

    1. - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    2. {
    3. CGPoint aktuelleMitte = [[touches anyObject] locationInView:nil];
    4. float ballSize=50.0f;
    5. float holeSize=50.0f;
    6. CGPoint newPoint=_ball.frame.origin;
    7. newPoint.x=aktuelleMitte.x;
    8. newPoint.y=aktuelleMitte.y-ballSize/2;
    9. _ball.center=newPoint;
    10. if(CGRectIntersectsRect(CGRectMake(_ball.center.x, _ball.center.y, ballSize, ballSize), CGRectMake(_hole.center.x, _hole.center.y, holeSize, holeSize)))
    11. {
    12. NSLog(@"treffer");
    13. }
    14. }
    Alles anzeigen
  • Hey danke das hab ich einigermaßen verstanden :D
    nur muss ich jetzt noch die Werte anpassen. Mit deinen Werten (hab ich einfach mal probiert) haut er mir den Ball ganz unten rechts in die Ecke des Bildschirms und gibt mir bei jeder Bewegung einen Treffer aus.
    Wenn ich woanders im Bildschirm drücke springt der Ball an diese Position und wenn ich mich dann mit dem Ball in die nähe des Loches bewege springt der Ball immer zwischen dem Loch und der aktuellen Touchposition hin und her.

    Was sind das denn für float Werte?

    Hier der Code den Ich jetzt benutzt habe:

    Quellcode

    1. - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    2. {
    3. CGPoint aktuelleMitte = [[touches anyObject] locationInView:nil];
    4. float ballSize=50.0f;
    5. float holeSize=50.0f;
    6. CGPoint neueMitte = CGPointMake(self.center.x + (aktuelleMitte.x - touchPunkt.x),
    7. self.center.y + (aktuelleMitte.y - touchPunkt.y));
    8. float screenMitteX = CGRectGetMidX(self.bounds);
    9. if (neueMitte.x > self.superview.bounds.size.width - screenMitteX)
    10. neueMitte.x = self.superview.bounds.size.width - screenMitteX;
    11. else if (neueMitte.x < screenMitteX)
    12. neueMitte.x = screenMitteX;
    13. float screenMitteY = CGRectGetMidY(self.bounds);
    14. if (neueMitte.y > self.superview.bounds.size.height - screenMitteY)
    15. neueMitte.y = self.superview.bounds.size.height - screenMitteY;
    16. else if (neueMitte.y < screenMitteY)
    17. neueMitte.y = screenMitteY;
    18. self.center = neueMitte;
    19. self.highlighted = YES;
    20. CGPoint newPoint=ball.frame.origin;
    21. newPoint.x=aktuelleMitte.x;
    22. newPoint.y=aktuelleMitte.y-ballSize/2;
    23. ball.center=newPoint;
    24. if(CGRectIntersectsRect(CGRectMake(ball.center.x, ball.center.y, ballSize, ballSize), CGRectMake(loch.center.x, loch.center.y, holeSize, holeSize)))
    25. {
    26. // BRAUCHE ICH DEN ANIMATIONSBEFEHL JETZT NOCH???
    27. [UIView animateWithDuration:0.1
    28. animations:^{ ball.center = loch.center; }];
    29. NSLog(@"treffer");
    30. }
    31. }
    Alles anzeigen


    Danke nochmal ich glaube das geht in die Richtung wir ich es vorgehabt hab.
  • Ehrlich gesagt, verstehe ich überhaupt nicht was Dein Code machen soll, was willst Du denn erreichen?
    Mein Beispiel macht nix anderes, als eine Kollision zwischen den beiden Objekten zu tracken, die float-Werte sind die Größe der beiden.