1

我正在开发一个应用程序,当中心球的颜色与朝中心球颜色飞行的较小球匹配时,玩家得分。所以为了这个工作,我需要在“敌人”和“主球”发生碰撞时调用 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))
}
}
4

2 回答 2

3

问题是他将他的敌人命名为“enemyBall”,但在他的 didBeginContact 中查找了“enemy”这个词。

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

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

于 2016-11-14T12:38:24.447 回答
0

如上所述,您似乎拼错了节点名称。您正在碰撞方法中寻找“敌人”,但将您的敌人命名为“enemyBall”。这就是为什么我们应该总是创建常量来避免这种情况,例如

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

我也会尝试遵循 swift 指导方针,类、枚举和结构应该以大写字母开头。

希望这可以帮助

于 2016-11-14T11:52:27.567 回答