2016-11-13 5 views
1

Ich arbeite an einer App, dass, wenn die zentrale Ballfarbe mit einem kleineren Ball übereinstimmt, der auf die zentrale Ballfarbe fliegt, der Spieler einen Punkt erzielt. Damit dies funktioniert, brauche ich die Funktion didBeginContact, die aufgerufen wird, wenn der "Feind" und der "MainBall" kollidieren. Das einzige, was sich bewegt, ist der gegnerische Ball, der auf den stationären mainBall fliegt. Ich glaube, ich habe die Bitmasken korrekt eingestellt, aber die Funktion didBeginContact wird nicht aufgerufen. Kann jemand bitte helfen?didBeginContact wird nicht Swift genannt

Hier ist mein Code

struct bitMasks{ 
static let mainBallMask:UInt32 = 0x1 << 0 
static let enemyBall:UInt32 = 0x1 << 1 
} 
class GameScene: SKScene,SKPhysicsContactDelegate { 

var mainBall = SKSpriteNode() 
var ballSetToMainColor = true 
var enemyTimer = Timer() 
var hits = 0 

override func didMove(to view: SKView) { 
    self.physicsWorld.contactDelegate = self 
    mainBall = childNode(withName: "centralBall") as! SKSpriteNode 
    mainBall.zPosition = 1.0 
    mainBall.physicsBody = SKPhysicsBody(circleOfRadius: mainBall.size.width/2) 

    mainBall.physicsBody?.categoryBitMask = bitMasks.mainBallMask 
    mainBall.physicsBody?.collisionBitMask = bitMasks.enemyBall 
    mainBall.physicsBody?.contactTestBitMask = bitMasks.enemyBall 

    mainBall.physicsBody?.isDynamic = false 
    mainBall.physicsBody?.affectedByGravity = false 
    enemyTimer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(enemies), userInfo: nil, repeats: true) 
} 


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
    touchesCheckForChangedBall(touches: touches) 
} 

func didBegin(_ contact: SKPhysicsContact) { 
    let firstBody = contact.bodyA.node as! SKSpriteNode 
    let secondBody = contact.bodyB.node as! SKSpriteNode 
    if firstBody.name == "enemy" && secondBody.name == "centralBall"{ 
     collisionMain(enemy: firstBody) 
    }else if firstBody.name == "centralBall" && secondBody.name == "enemy"{ 
     collisionMain(enemy: secondBody) 
    } 
} 

func collisionMain(enemy: SKSpriteNode){ 
    hits += 1 
    enemy.removeAllActions() 
    enemy.removeFromParent() 
    print(hits) 

} 

func touchesCheckForChangedBall(touches: Set<UITouch>){ 
    for t in touches { 
     let location = t.location(in: self) 
     let nodes = self.nodes(at: location) 
     if nodes.isEmpty == false { 
      if let name = nodes[0].name{ 
       if name == "centralBall"{ 
        changeMainBallColor() 
       } 
      } 
     } 
    } 
} 

func changeMainBallColor(){ 
    ballSetToMainColor = !ballSetToMainColor 
    if ballSetToMainColor == true{ 
     mainBall.texture = SKTexture(imageNamed: "ball-mainColor") 
    }else{ 
     mainBall.texture = SKTexture(imageNamed: "ball-secondaryColor") 
    } 
} 

override func update(_ currentTime: TimeInterval) { 
    // Called before each frame is rendered 
} 

func getRandomImageColor()->String{ 
    let randVal = arc4random_uniform(2) 
    if randVal == 0{ 
     return "ball-secondaryColor" 
    }else{ 
     return "ball-mainColor" 
    } 
} 

func enemies(){ 
    let color = getRandomImageColor() 
    let enemy = SKSpriteNode(imageNamed: color) 
    enemy.size = CGSize(width: 30, height: 30) 
    enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.size.width/2) 
    enemy.physicsBody?.categoryBitMask = bitMasks.enemyBall 
    enemy.physicsBody?.collisionBitMask = bitMasks.mainBallMask 
    enemy.physicsBody?.contactTestBitMask = bitMasks.mainBallMask 
    enemy.name = "enemyBall" 
    enemy.physicsBody?.isDynamic = true 
    enemy.physicsBody?.affectedByGravity = false 
    let randomPositionNumber = arc4random() % 3 
    switch randomPositionNumber{ 
    case 0: 
     enemy.position.x = 0 
     let posY = arc4random_uniform(UInt32(frame.size.height)) 
     enemy.position.y = CGFloat(posY) 
     self.addChild(enemy) 
     break 
    case 1: 
     enemy.position.y = frame.size.height 
     let posX = arc4random_uniform(UInt32(frame.size.width)) 
     enemy.position.x = CGFloat(posX) 
     self.addChild(enemy) 
     break 
    case 2: 
     enemy.position.x = frame.size.width 
     let posY = arc4random_uniform(UInt32(frame.size.height)) 
     enemy.position.y = CGFloat(posY) 
     self.addChild(enemy) 
     break 
    default: 
     break 
    } 
    enemy.run(SKAction.move(to: mainBall.position, duration: 3)) 
} 
} 
+0

Sie haben dynamische auf false gesetzt, jedes Objekt, das bewegt und braucht Physik muss dies auf True gesetzt haben – Knight0fDragon

+0

@ Knight0fDragon das einzige, was bewegt ist der Ball des Gegners Sorry ich hätte das klar gemacht Ich werde die Frage bearbeiten – spies9149

+3

Sie nennen Feind 'FeindBall', aber Ihr Kontakt sucht nach' Feind' – Knight0fDragon

Antwort

1

Wie oben erwähnt es scheint, dass Sie Ihren Knotennamen falsch geschrieben haben. Du suchst in der Kollisions-Methode nach "Feind", benennst deine Gegner aber "FeindBall". Deshalb sollten wir immer Konstanten erstellen, um dies z.

let enemyName = "Enemy" 

und als es verwenden, wie so

enemy.name = enemyName 

können Sie auch versuchen, Ihre Kollisionsverfahren wie das Schreiben, das es etwas schöner lesen machen sollte, und Sie müssen nur 1 if-Anweisung pro Kollision. Auf diese Weise benötigen Sie keine Knotennamen zum Vergleichen von Körpern.

func didBegin(_ contact: SKPhysicsContact) { 

    let firstBody: SKPhysicsBody 
    let secondBody: SKPhysicsBody 

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask { 
     firstBody = contact.bodyA 
     secondBody = contact.bodyB 
    } else { 
     firstBody = contact.bodyB 
     secondBody = contact.bodyA 
    } 

    // Main ball with enemy or enemy with main ball 
    if (firstBody.categoryBitMask == bitMasks.mainBall) && (secondBody.categoryBitMask == bitMasks.enemy) { 
     // do something 
    } 
} 

Ich würde auch versuchen, die schnellen guidlines, Klassen, Aufzählungen und Strukturen folgen sollte mit Großbuchstaben beginnen.

this helps

+0

Er sagte bereits, dass sich der Hauptball nicht bewegt, so dass es dynamisch zu true setzt, dient keinem Zweck – Knight0fDragon

3

Ausgabe war er seinen Feind "enemyBall" genannt., Sah aber für das Wort "Feind" in seiner didBeginContact.

Aus diesem Grunde ist es eine schlechte Idee ist es, einen String-Vergleich zu verwenden (sowie es als andere Vergleiche langsamer ist)

Ich empfehle categoryBitmask Überprüfung zuerst nach dem Namen oder Klasse je nachdem, wie spezifisch für eine gefolgt würde, überprüfen Sie, dass Sie brauchen.

Verwandte Themen