2015-01-15 13 views
5
func didBeginContact(contact: SKPhysicsContact) { 
    if (contact.bodyA.categoryBitMask & BodyType.shield.rawValue) == BodyType.shield.rawValue { 
     contact.bodyB.node?.removeFromParent() 
     counter++ 
     println(counter) 


    } else if (contact.bodyB.categoryBitMask & BodyType.shield.rawValue) == BodyType.shield.rawValue { 
     contact.bodyA.node?.removeFromParent() 
     counter++ 
     println(counter) 
    } 
} 

Ein Physik Körper ist aus einer Textur namens shield.physicsBody = SKPhysicsBody(texture: shieldTexture, size: shieldTexture.size()) didBeginContact wird mehrmals für die gleiche SKPhysicsBody

die andere aus einem Kreis ist sand.physicsBody = SKPhysicsBody(circleOfRadius: sand.size.width/2)

Wenn der Abschleppwagen-Kontaktobjekte einander manchmal sand.physicsBody = SKPhysicsBody(circleOfRadius: sand.size.width/2) aufgerufen wird mehrmals. Wie bekomme ich es nur für jedes Objekt einmal aufgerufen werden, obwohl ich es aus dem Eltern entfernen, sobald es kontaktiert.

+2

Ich glaube, dies funktioniert wie vorgesehen, da Körper von Textur mehrere Formen intern erzeugen kann, jedes kann ein Kontakt Ereignis verursachen. Durch Entfernen des Knotens wird der Körper erst nach Abschluss des Physiksimulationsschritts entfernt. Sie müssen den Knoten oder den Körper in diesem Kontakt-Ereignis manuell als "markiert" markieren, so dass Sie nachfolgende Kontakt-Ereignisse desselben Körpers überspringen können. – LearnCocos2D

+0

Ich wünschte, es gäbe eine Option für SKPhysicsBody von Textur, um es durch Parameter zu setzen, so dass es genau wie z. SKPhysicsBody von circleOfRadius zählt also NUR 1 Treffer/Kontakt, da dies in manchen Fällen sehr wünschenswert wäre, als eine zusätzliche Logik zu erstellen, einschließlich der folgenden Antwort. Außerdem könnte es Ressourcen sparen, um nicht mehr Kontakte zu erkennen, wenn sie nicht benötigt werden. –

Antwort

2

Ich habe herausgefunden, wie func didBeginContact(contact: SKPhysicsContact) nur einmal aufgerufen werden kann. Dies erlaubt Physikkörpern mit einer Textur SKPhysicsBody(texture: size:), Kollisionen einmal zu zählen, obwohl diese Funktion in der Realität (aufgrund der Natur des physikalischen Körpers der Textur) mehrfach aufgerufen wird.

Schritt 1:

einen Namen erstellen Objekt für die SKSpriteNode (die wir für dieses Beispiel verwenden Ball wird) und setzen ihn auf einen eindeutigen Namen gleich. Wir können dies tun, indem Sie eine int

Dies ermöglicht für einen eindeutigen Namen evertime das Objekt erstellt wird.

Schritt 2:

ein Array erstellen diese zu halten, den Ball in dem Array anhängen, erhöht die Anzahl

var array: [String] = [] 
    var number = 0 

ball.name = "ball \(number)" 
array.append(ball.name!) 
number ++ 

Schritt 3: Nun in den func didBeginContact(contact: SKPhysicsContact) herauszufinden, ob der Name in der ist Array. Wenn die Punktzahl erhöht wird, entfernen Sie den Knoten und entfernen Sie den Namen aus dem Array. Wenn der Name nicht im Array ist, mache nichts.

Durch das Entfernen des Namens aus dem Array können wir den Funktionsaufruf nur noch einmal zählen.

func didBeginContact(contact: SKPhysicsContact) { 
    if (contact.bodyA.categoryBitMask & BodyType.shield.rawValue) == BodyType.shield.rawValue { 
     var name = contact.bodyB.node?.name! 
     let index = find(array, name!) 

     if contains(array, name!) { 
      score++ 
      contact.bodyB.node?.removeFromParent() 
      array.removeAtIndex(index!) 
     } 
    } 
} 
+1

Kann man nicht einfach den SKSpriteNode zum Array hinzufügen? Es wird als Referenz weitergegeben, damit wir sie vergleichen können. Ich sehe nicht, warum wir eindeutige Namen vergeben müssen. – 3366784

0

LearnCocos2D richtig ist, rufen SKPhysicsbody didBeginContact wird kontinuierlich solange SKphysicsbody der beiden Objekte sind in Kontakt, weil die Form, die wir in SKPhysicsBody(texture:xxx, size:xx) erlaubt in mehreren Formen und Gestalten kommen kann.

Für diejenigen, die es nur einmal erkennen müssen, müssen wir nur einen booleschen als Flag verwenden, um zu überprüfen, ob die Erkennung abgeschlossen ist und mit.

Hier ist, wie ich es tun:

  1. Deklarieren Sie eine var boolean:

    var contactDone = Bool() 
    
  2. es zu Beginn des Programms initialisiert werden (zunter didMoveToView)

    contactDone = false 
    
  3. die Überprüfung Sie in didBeginContact:

    func didBeginContact(contact:SKPhysicsBody){ 
    
    if((contact.bodyA.categoryBitMask) == scoreCategory ||  (contact.bodyB.categoryBitMask) == scoreCategory){ 
    
         if (contactDone == false){ 
    
         // Increment score   
         score++ 
    
         // Set flag to disable multiple calls by checking in didEndContact 
         contactDone = true 
    
         } 
    } 
    } 
    
  4. löschen, die die Flagge wieder lassen überprüfen in didEndContact:

    func didEndContact(contact: SKPhysicsContact) { 
    
    if((contact.bodyA.categoryBitMask) == scoreCategory || (contact.bodyB.categoryBitMask) == scoreCategory){ 
    
          if(contactDone == true){ 
    
           contactDone = false 
    
          } 
    
    } 
    
    } 
    

Es funktionierte wie es tat, als ich SKPhysicBody(circleOfRadius: object.size.height/2) verwendete.

+0

Funktioniert nicht, wenn ich 'SKPhysicsBody (Textur: ghostTexture, Größe: Obj.size) verwende' – Danny182

0

Sie können es in diesem Fall ohne das Array arbeiten lassen. Statt dessen:

contact.bodyA.node?.removeFromParent() 
counter++ 

Verwendung so etwas wie dieses:

if let node = contact.bodyA.node as? SKSpriteNode { 
    if node.parent != nil { 
     node.removeFromParent() 
     counter++ 
    } 
} 

Auf dem ersten Kontakt entfernen Sie den Knoten aus dem übergeordneten, auf den nachfolgenden Aufrufen den Code in der if-Anweisung übersprungen.

1

Es gibt eine sehr einfache Lösung, wenn Sie contactbitmask verwenden, um zu ermitteln, welche Kollisionen zu erfassen sind.

aktualisieren nur die categoryBitMask des Objekts, das Sie wollen nicht immer wieder auf einen neuen Wert festgestellt werden, die verwendet wird, ist nicht so das System tut t nachfolgende Funktionsaufrufe mehr als relevant erachten.

Verwandte Themen