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

  • Hi,
    sry vlt. hab ich mich unverständlich ausgedrückt :( , also ich möchte, dass der Ball sich nicht aus dem Bildschirm bewegt also am Rand stoppt. Dafür hab ich diesen Code der auch bisher gut funktioniert.

    Quellcode

    1. - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    2. {
    3. // Den aktuellen Ort bei bewegung ermitteln.
    4. CGPoint aktuelleMitte = [[touches anyObject] locationInView:self];
    5. // Den Punkt bestimmen an dem das Objekt bewegt wird.
    6. CGPoint neueMitte = CGPointMake(self.center.x + (aktuelleMitte.x - touchPunkt.x),
    7. self.center.y + (aktuelleMitte.y - touchPunkt.y));
    8. // Wir bleiben mit dem Objekt im Bildschirm.
    9. float screenMitteX = CGRectGetMidX(self.bounds);
    10. // wenn zu weit rechts ...
    11. if (neueMitte.x > self.superview.bounds.size.width - screenMitteX)
    12. neueMitte.x = self.superview.bounds.size.width - screenMitteX;
    13. // wenn zu weit links ...
    14. else if (neueMitte.x < screenMitteX)
    15. neueMitte.x = screenMitteX;
    16. float screenMitteY = CGRectGetMidY(self.bounds);
    17. // wenn zu weit unten ...
    18. if (neueMitte.y > self.superview.bounds.size.height - screenMitteY)
    19. neueMitte.y = self.superview.bounds.size.height - screenMitteY;
    20. // wenn zu weit oben ...
    21. else if (neueMitte.y < screenMitteY)
    22. neueMitte.y = screenMitteY;
    23. // Setzt Objekt neue Mitte.
    24. self.center = neueMitte;
    Alles anzeigen


    Und dann möchte ich noch, dass wenn der Ball in die nähe des Loch´s kommt er wie ein Magnet von der Lochmitte angezogen wird und dort bleibt. Und da hänge ich im Moment.
    Ich habe dafür versucht die CGRectIntersectsRect Methode einzusetzen aber da passiert leider rein garnichts und ich möchte gerne wissen wieso und wie ich das ans laufen kriege.

    Quellcode

    1. CGRect lochKlein = CGRectInset(loch.frame, +20.0, +20.0);
    2. if (CGRectIntersectsRect (ball.frame, lochKlein )) {
    3. [UIView animateWithDuration:0.01
    4. animations:^{ ball.center = loch.center; }];
    5. NSLog(@"eingelocht");
    6. }
    Alles anzeigen
  • Gibt es denn eine korrekte Kollision zwischen dem Loch und dem Ball?
    Du willst ja aber das der Ball an das Loch "gezogen" wird, das kannst Du zwar auch mit ner Rect->Rect Kollision prüfen, ich würd aber dazu den Weg mit dem Vektor nehmen.
  • Ok das hab ich mir gedacht ;) da ich ja mit dem Storyboard arbeite.
    Alles was ich dazu jetzt finden konnte (in meinen Büchern und Google) war etwas zu encodeWithCoder bzw. initWithCoder.

    Also hab ich die in meinen code eingebracht:

    Quellcode

    1. - (void)encodeWithCoder:(NSCoder *)enCoder {
    2. [super encodeWithCoder:enCoder];
    3. [enCoder encodeObject:self.ball forKey:(NSString *)ball];
    4. [enCoder encodeObject:self.loch forKey:(NSString *)loch];
    5. }
    6. - (id)initWithCoder:(NSCoder *)aDecoder {
    7. if(self = [super initWithCoder:aDecoder]) {
    8. self.ball = [aDecoder decodeObjectForKey:(NSString *)ball];
    9. self.loch = [aDecoder decodeObjectForKey:(NSString *)loch];
    10. }
    11. return self;
    12. }
    Alles anzeigen


    hat jetzt aber noch nichts geändert. (Wäre ja auch zu einfach :D )

    Bin ich auf dem richtigen Weg?
    Brauche ich encodeWithCoder, oder reicht initWithCoder?
    Wieso geht es denn nicht mit initWithFrame?
  • Achsoooo ja das hab ich gemacht ;)

    Jetzt wird's kompliziert :D ich hab im IB einen einen ViewController mit einer eigenen Klasse in dem ich die Outlets verknüpft hab (enthält aber keinen weiteren Code) und einen UIView, welcher mein Hintergrundbild beinhaltet, der eine eigene Klasse hat wo ich ebenfalls die Outlets definiert und verknüpft hab.

    Selbst wenn ich diesen Teil:

    Quellcode

    1. CGRect lochKlein = CGRectInset(loch.frame, +20.0, +20.0);
    2. NSLog(@"ball:%@\nloch:%@",ball,loch);
    3. if (CGRectIntersectsRect (ball.frame, lochKlein )) {
    4. [UIView animateWithDuration:0.01
    5. animations:^{ ball.center = loch.center; }];
    6. NSLog(@"eingelocht");
    7. }
    Alles anzeigen

    in touchesMoved der ViewController-Klasse einfüge passiert nichts :S noch nicht einmal in der Konsole wird etwas ausgegeben.
  • Also uffpasse:

    Du nimmst nen Viewcontroller, auf dem platzierst Du 2 UIView's.
    Mach die beiden Views farbig, dann musst Du erst mal keinen Code in die draw-Methode der beiden Klassen einbauen, die Du als nächstes erstellst.
    Du erstellst Dir 2 Klassen beide leitest Du von UIView ab.
    Eine Ball und eine Hole.
    Im IB stellst Du für Class der View's einmal Ball und einmal Hole als Klasse ein.
    In Deinem Viewcontroller machst Du 2 Connections zu den beiden Views.
    Eine ball und eine hole.

    Jetzt hast Du im Viewcontroller Zugriff auf die beiden Instanzen Deiner Klassen Ball und Hole und kannst mit denen beiden arbeiten.
    Den Rest haben wir Dir ja schon gesagt, geschrieben.
  • Hallöchen hab leider jetzt erst wieder Zeit gefunden an meinem Projekt weiter zu Basteln :)

    ich hab in einem Testprojekt alles genau so gemacht wie du es geschrieben hast ... und !? ... exakt das selbe Verhalten wie in meinem Projekt ;(

    Ich habe hier mal das Projekt hochgeladen damit ihr euch ein Bild davon machen könnt wie ich das ganze hingestellt habe, dann könnt ihr selber mal probieren was ich meine : EFTest.zip

    Wenn ich den Ball (Rot) in das Loch (Grün) ziehe soll es so aussehen als ob es wie von einem Magnet in die Mitte gezogen wird .. blablabla kennt ihr ja schon.

    Aber nur wenn ich den Center vom Ball Frame in den Inset vom Loch ziehe und dann auf das Loch drücke und dragge tritt mein gewünschter Effekt ein. Ich verstehe einfach nicht was ich da falsch mache so schwer kann das doch nicht sein.
  • Probier das mal, hab es schnell zusammen genagelt:

    Quellcode

    1. - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    2. {
    3. int dist=[self getDistance:CGPointMake(_ball.frame.origin.x, _ball.frame.origin.y) p2:CGPointMake(_hole.frame.origin.x, _hole.frame.origin.y)];
    4. if(dist<170)
    5. [UIView animateWithDuration:1.0
    6. animations:^{[_ball setFrame:CGRectMake(_hole.frame.origin.x, _hole.frame.origin.y, 10, 10)]; }];
    7. else
    8. _ball.center=[[touches anyObject] locationInView:self.view];
    9. NSLog(@"distanz:%d", [self getDistance:CGPointMake(_ball.frame.origin.x, _ball.frame.origin.y) p2:CGPointMake(_hole.frame.origin.x, _hole.frame.origin.y)]);
    10. }
    11. -(int)getDistance:(CGPoint)p1 p2:(CGPoint)p2
    12. {
    13. return sqrtf( (p2.x - p1.x)*(p2.x - p1.x) + (p2.y - p1.y)*(p2.y - p1.y) );
    14. }
    Alles anzeigen



    Setzt den Ball weit genug weg im IB
  • Je nachdem wie Du drauf reagieren willst, wenn der Ball reingezogen wurde, ist der Ansatz aber völlig unbrauchbar, weil
    1. das Ganze in der touchesMoved abgefragt und gehandelt wird, also auch nur dann reagiert wenn Du das Dinges rum schiebst
    2. du keine saubere Möglichkeit mehr hast einzugreifen, wenn die Animation angeschuckt wurde
    Probiers jetzt aber erst mal so aus um zu verstehen, was da passiert. Wenn Du auf die Kollision "ordentlich" reagieren willst, brauchst Du nen Timer
    der ständig abfrägt ob ne Kollision vorliegt. Das hat den Vorteil, das Ganze funktioniert auch ohne das Du die Finger drauf hast.
  • Habs probiert mit dem selben Ergebnis :( nur wenn ich den Ball in die nähe bringe und dann auf das Loch drücke und dragge reagiert die Methode wie sie soll.


    Im Endeffekt macht dein Code das selbe wie meiner, welcher für meine Zwecke auch völlig reicht ;) trotzdem danke ich dir :!: für die Hilfe.

    Kannst dir vlt. mal das Projekt angucken was ich erstellt habe ich denke da solltest du besser erkennen was ich meine. Hab es hier noch einmal mit deiner Methode hochgeladen : EFTest2.zip

    Ich bin kurz vorm durchdrehen der Fehler muss irgend ein anderer sein bestimmt sogar nur eine Kleinigkeit :wacko: .
  • OK danke für das Projekt jetzt hab ich zumindest schonmal etwas rausgefunden :D

    wenn ich diesen Code :

    Quellcode

    1. - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
    2. {
    3. // Wenn der Bildschirm berührt wird, wird erfasst wo er berührt wurde.
    4. touchPunkt = [[touches anyObject] locationInView:self];
    5. }
    6. - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    7. {
    8. // Den aktuellen Ort bei bewegung ermitteln.
    9. CGPoint aktuelleMitte = [[touches anyObject] locationInView:self];
    10. // Den Punkt bestimmen an dem das Objekt bewegt wird.
    11. CGPoint neueMitte = CGPointMake(self.center.x + (aktuelleMitte.x - touchPunkt.x),
    12. self.center.y + (aktuelleMitte.y - touchPunkt.y));
    13. // Wir bleiben mit dem Objekt im Bildschirm.
    14. float screenMitteX = CGRectGetMidX(self.bounds);
    15. // wenn zu weit rechts ...
    16. if (neueMitte.x > self.superview.bounds.size.width - screenMitteX)
    17. neueMitte.x = self.superview.bounds.size.width - screenMitteX;
    18. // wenn zu weit links ...
    19. else if (neueMitte.x < screenMitteX)
    20. neueMitte.x = screenMitteX;
    21. float screenMitteY = CGRectGetMidY(self.bounds);
    22. // wenn zu weit unten ...
    23. if (neueMitte.y > self.superview.bounds.size.height - screenMitteY)
    24. neueMitte.y = self.superview.bounds.size.height - screenMitteY;
    25. // wenn zu weit oben ...
    26. else if (neueMitte.y < screenMitteY)
    27. neueMitte.y = screenMitteY;
    28. // Setzt Objekt neue Mitte.
    29. self.center = neueMitte;
    30. }
    Alles anzeigen


    bei dir in die Ball.m einfüge (und touchPunkt in der .h deklariere) tritt in deinem Projekt der selbe Fehler auf wie bei mir.
    Jetzt weis ich wenigstens das es an diesem Teil liegt aber der ist mir sehr wichtig da ich nicht möchte das man das Objekt aus dem Bildschirm raus bewegen kann und es sich dort bewegt wo man es anfasst.

    Wie krieg ich das jetzt am besten hin?



    edit:

    Wenn ich diesen code in die ViewController Klasse einfüge geht es ja nicht weil sie nicht von UIView bzw. UIImageView abstammt.

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

  • Ja verstehe ich, ich möchte ja auch keine "Fertige Lösung" aber ich dachte jemand könnte mir erklären "warum" es so nicht geht wie ich es gedacht habe.

    Ich hab da noch ein Buch "Spiele entwickeln" von Thomas Lucka welches ich noch nicht durchgearbeitet habe.

    Ich war der Meinung, dass die im Buch beschriebenen Methoden viel zu kompliziert für mein Projekt sind und das es viel einfacher geht z.B. mit dem Storyboard. Im Buch macht er alles per Code und ich dachte so ein Aufwand ist heutzutage nicht mehr nötig.

    Aber du hast trotzdem recht die Grundkenntnisse müssen erstmal sitzen, deswegen werde ich mich nochmal näher mit dem Buch befassen und sehen ob es mich in meinem Projekt weiter bringt. :S

    Für weitere Hilfen und Erklärungen wäre ich trotzdem dankbar.
  • Klar geht das nicht, z.B. verweist du

    Quellcode

    1. CGPoint aktuelleMitte = [[touches anyObject] locationInView:self];

    self ist der View, wenn Du dem im Controller aufrufst geht das natürlich nicht, dann muss das [self view] heissen.


    Solche Sachen gehören aber in den Controller und nicht in den View (Ball in deinem Fall)
  • Ja das hab ich ja auch schon gemacht, nur geht dann gar keine Bewegung mehr mit den Objekten (Ball) ich vermute dann müsste ich diesen Code explizit für jedes Objekt schreiben statt für self.view

    Wäre das nicht kontraproduktiv, da ich später viele ViewController mit vielen Objekten hätte.