2016-03-31 9 views
1

Ich habe ein Objekt zwischen zwei Balken gehalten. Ich habe Kollisionen eingerichtet, aber ich erhalte die Druckmeldung "Wir haben Kontakt" nicht, wenn wir mit der oberen oder unteren Leiste Kontakt aufnehmen, und ich bin mir nicht sicher warum? Ich denke, es könnte etwas mit der Grenzphysik zu tun haben. Das Bild unten soll ein Beispiel für die Balken geben, wo das Objekt zwischen ihnen gehalten wird. enter image description hereKollisionen in SpriteKit

 var gameOver = false 



override func didMoveToView(view: SKView) { 
    scene?.scaleMode = SKSceneScaleMode.AspectFill 


    self.physicsWorld.gravity = CGVectorMake(0.0, 2.0) 
    physicsWorld.contactDelegate = self 

    object = SKSpriteNode(imageNamed: "object") 
    object.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)) 
    object.physicsBody = SKPhysicsBody(circleOfRadius: object.size.width/0.32) 

    object.physicsBody?.dynamic = true 
    object.physicsBody?.allowsRotation = true 
    self.addChild(object) 
    object.zPosition = 2 


    struct ColliderType { 

     static let object: UInt32 = 0x1 << 0 
     static let boundary: UInt32 = 0x1 << 1 


    } 
    let boundary = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 253, y: 138, width:515, height:354)) 
    self.physicsBody = boundary 
    self.physicsBody?.friction = 0 
    let push = CGVectorMake(10, 10) 
    object.physicsBody?.applyImpulse(push) 


    object.physicsBody?.categoryBitMask = ColliderType.object 
    object.physicsBody?.contactTestBitMask = ColliderType.boundary 
    object.physicsBody?.collisionBitMask = ColliderType.boundary 


    boundary.contactTestBitMask = ColliderType.object 
    boundary.categoryBitMask = ColliderType.boundary 
    boundary.collisionBitMask = ColliderType.object 


    func didBeginContact(contact:SKPhysicsContact) { 
     print("We have Contact") 

     gameOver = true 
     self.speed = 0 

    } 

Antwort

2

Versuchen Sie, die Web-und Stackoverflow, bevor er fragte eine Frage gerade weil es eine Menge von Tutorials im Internet und sogar Stack-Überlauf darüber. Diese Frage könnte sogar geschlossen werden, weil die Kollisionserkennung eine der Grundlagen in SpriteKit ist und viel über SO gefragt wurde.

Wie auch immer, es gibt einige Fehler/Auslassungen in Ihrem Code, also schauen wir es uns an.

1) Sie müssen den physics world contact delegate in Ihrer Szenen-Methode "didMoveToView" einstellen, so dass er tatsächlich nach Kontakten lauscht. Dies ist die Nummer 1, die Menschen, einschließlich mir, vergessen und sich stundenlang fragen, warum nichts funktioniert.

physicsWorld.contactDelegate = self 

2) Sie sind nicht auch Ihre Sprites ein physicsBody geben

object.physicsBody = SKPhysicsBody(...) 

Sie müssen sie immer einen Physik Körper geben erste und als Satz Eigenschaften wie contactTestBitMasks usw.

3) Versuchen Sie es mit? Anstatt von ! im Umgang mit Optionals, um Null-Abstürze zu vermeiden. Versuche das immer zu tun, obwohl du weißt, dass es nicht gleich Null ist. So sagen

...physicsBody?.contactTestBitMask... 

statt

...physicsBody!.contactTestBitMask... 

Sie manchmal tun es, und manchmal nicht.

In Ihrem aktuellen Code könnten Sie einen Absturz bekommen, weil das Objekt keinen physicsBody hat, aber Sie sind gezwungen, es auszupacken, im Wesentlichen zu sagen, dass es einen Physikkörper hat, der gefährlich ist.

Zum Beispiel im Code diese Zeile sollte

object.physicsBody?.applyImpulse(push) 

nicht funktionieren, da es keine Physik Körper auf dem Objekt ist, sondern weil es nicht zwingen wird Abwickeln (?) Nichts passiert. Versuchen Sie, diese Zeile mit a zu ändern! und du solltest einen Crash bekommen. Also immer benutzen? im Umgang mit Optionals und wenn der Compiler das auch zulässt.

Auch diese Zeile sollte sein, nachdem Sie das Objekt Sprite nicht zuvor eingerichtet haben.

4) Versuchen Sie, Ihre Physik Kategorien anders zu schreiben, Ihr Weg wird sehr schnell verwirrend, wenn Sie weitere Kategorien hinzufügen, weil Sie nicht nur die letzte Zahl erhöhen können. In Ihrem Beispiel muss der nächste Collider-Typ also 4, 8, 16 usw. sein.

Versuchen Sie dies stattdessen, wo Sie nur die letzte Zahl um 1 erhöhen müssen.

struct ColliderType { 
    static let object: UInt32 = 0x1 << 0 
    static let boundary: UInt32 = 0x1 << 1 
    .... 
} 

als es verwenden, wie so

...contactTestBitMask = ColliderType.object 
... 

Sie sollten ganze Code so aussehen

struct ColliderType { 

static let object: UInt32 = 0x1 << 0 
static let boundary: UInt32 = 0x1 << 1 


} 

    class GameScene: SKScene, SKPhysicsContactDelegate { 

var gameOver = false 

var object: SKSpriteNode! 


override func didMoveToView(view: SKView) { 
    scene?.scaleMode = SKSceneScaleMode.AspectFill 


    self.physicsWorld.gravity = CGVectorMake(0.0, 2.0) 
    physicsWorld.contactDelegate = self 

    object = SKSpriteNode(imageNamed: "Spaceship") 
    object.zPosition = 2 
    object.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)) 
    object.physicsBody = SKPhysicsBody(circleOfRadius: object.size.width/0.32) 

    object.physicsBody?.dynamic = true 
    object.physicsBody?.allowsRotation = true 
    object.physicsBody?.categoryBitMask = ColliderType.object 
    object.physicsBody?.contactTestBitMask = ColliderType.boundary 
    object.physicsBody?.collisionBitMask = ColliderType.boundary 
    self.addChild(object) 


    let boundary = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 253, y: 138, width:515, height:354)) 
    self.physicsBody = boundary 
    self.physicsBody?.friction = 0 
    boundary.contactTestBitMask = ColliderType.object 
    boundary.categoryBitMask = ColliderType.boundary 
    boundary.collisionBitMask = ColliderType.object 

    let push = CGVectorMake(10, 10) 
    object.physicsBody?.applyImpulse(push) 
} 


func didBeginContact(contact:SKPhysicsContact) { 
    print("We have Contact") 

    gameOver = true 
    self.speed = 0 
    } 
} 

this helps

+0

Sie haben einen winzigen Fehler ... Um eine Szene zum Abhören des Kontakts zu machen, setzen Sie den Delegaten innerhalb einer Szene, nicht innerhalb eines 'viewDidLoad', das Mitglied eines View-Controllers ist. – Whirlwind

+0

Ja, tut mir leid, ich sollte DidMoveToView sagen. Wird meine Antwort aktualisieren. Danke – crashoverride777

+0

Hallo, zuerst einmal vielen Dank für Ihre ausführliche Antwort! Ich wollte erwähnen, dass ich einen physikalischen Körper hatte, der für mein Objekt eingerichtet war und der Befehl zum Delegieren des Kontakts bereits eingegeben wurde, also wollte ich mich entschuldigen, weil ich völlig vergessen hatte, diesen Code zum Zeitpunkt des Schreibens der ursprünglichen Frage hinzuzufügen. Mit meinem aktuellen Code kann das Objekt die inneren Kanten der Balken gut berühren und ist zwischen ihnen enthalten, aber ich bekomme keine Benachrichtigung darüber, dass ich Kontakt hergestellt habe. – Seed12

0

Sie müssen sicher sein, dass die beiden Kollisionsformen im selben Kollisionsraum, wenn sie nicht im selben Raum sind, wird der Kollisionsdetektionsalgorithmus niemals i sein navoked. Über den Kommentar von Seed12 müssen die beiden Objekte kein starrer Körper (physicsBody) sein, um auf das Vorhandensein von Kollisionen zwischen ihnen überprüft zu werden.

+0

Hallo, danke für deine Antwort! Beide Kollisionsformen sind momentan in der Szene sichtbar und das Objekt kann die inneren Kanten der Balken berühren (wo der Kontakt auch sein sollte), aber ich bekomme keine Benachrichtigung, die mich darüber informiert, dass der Kontakt hergestellt wurde. – Seed12