didBeginContact没有被称为Swift

时间:2016-11-13 21:04:17

标签: swift sprite-kit skphysicsworld

我正在开发一款应用程序,当中心球颜色与向中心球颜色飞行的较小球匹配时,玩家得分。 所以为了这个工作我需要didBeginContact函数来调用“敌人”和“mainBall”碰撞。唯一正在移动的是敌人的球,因为它飞向固定的主球 我相信我已正确设置了位掩码,但未调用didBeginContact函数。 有人可以帮忙吗?

这是我的代码

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))
}
}

2 个答案:

答案 0 :(得分:3)

问题是他将他的敌人命名为“enemyBall”。但是在他的didBeginContact中寻找“敌人”一词。

这就是为什么使用字符串比较是一个坏主意(以及它比其他比较慢)

我建议首先检查categoryBitmask,然后根据您需要的检查的具体情况来检查名称或类别。

答案 1 :(得分:1)

如上所述,您似乎拼错了节点名称。你在找&#34;敌人&#34;在碰撞方法,但命名你的敌人&#34; enemyBall&#34;。这就是为什么我们应该总是创建常数来避免这种情况。

let enemyName = "Enemy"

而不是像这样使用

enemy.name = enemyName

您也可以尝试编写这样的碰撞方法,这样可以使它读得更好,每次碰撞只需要1个if语句。此外,您不需要节点名称来比较实体。

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
    }
}

我也会尝试遵循快速的指导,类,枚举和结构应该以大写字母开头。

希望这有帮助