ios - 没有在 Swift 中正确检测碰撞

标签 ios swift sprite-kit

我正在制作一个从屏幕顶部生成立方体的游戏,当它们被触摸时它们会消失。我将对象位置设置为用户触摸的点。它运行函数 DidBeginContact ,但它似乎没有检测到我的两个 View :

func didBeginContact(contact: SKPhysicsContact) {
        var firstBody : SKPhysicsBody = contact.bodyA
        var secondBody : SKPhysicsBody = contact.bodyB

        print("didbegincontact")
        if ((firstBody.categoryBitMask == PhysicsCategory.RedSquare) && (secondBody.categoryBitMask == PhysicsCategory.touchlocation)) || ((firstBody.categoryBitMask == PhysicsCategory.touchlocation) && (secondBody.categoryBitMask == PhysicsCategory.RedSquare)) {
            collisionwithredsquare(firstBody.node as! SKSpriteNode)
            print("Done")

        }
    }

它正在打印“didBegincontact”,所以我知道该函数正在运行,但 if 语句不起作用。

所有代码如下:

import SpriteKit

struct PhysicsCategory {
    static let RedSquare : UInt32 = 1
    static let touchlocation : UInt32 = 2
    static let BlueSquare : UInt32 = 3
}

class GameScene: SKScene, SKPhysicsContactDelegate {

     var animator : UIDynamicAnimator?
     let blueSquare = SKSpriteNode()
     let redSquare = SKSpriteNode()
    var scorenumber = 0
    var ground = SKSpriteNode()
    var touchpoint = SKSpriteNode()

    override func didMoveToView(view: SKView) {
        /* Setup your scene here */
        physicsWorld.contactDelegate = self
        physicsWorld.gravity = CGVector(dx: 1.0, dy: -9.0)


       /* let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
        // 2. Set the friction of that physicsBody to 0
        borderBody.friction = 0
        // 3. Set physicsBody of scene to borderBody
        self.physicsBody = borderBody */


        touchpoint = SKSpriteNode(imageNamed:"Spaceship")
        touchpoint.physicsBody?.categoryBitMask = PhysicsCategory.touchlocation
        touchpoint.physicsBody?.contactTestBitMask = PhysicsCategory.RedSquare
        touchpoint.physicsBody?.affectedByGravity = false

        touchpoint.xScale = 0.5
        touchpoint.yScale = 0.5


       self.addChild(touchpoint)

        let width = UInt32(self.frame.size.width)

        let X = arc4random() % width


        ground = SKSpriteNode(imageNamed: "Ground")
        ground.setScale(1.0)
        ground.position = CGPoint(x: self.frame.width / 2, y: 5)
        ground.physicsBody = SKPhysicsBody(rectangleOfSize: ground.size)
        ground.physicsBody?.affectedByGravity = false
        ground.physicsBody?.dynamic = false

        ground.zPosition = 3

        self.addChild(ground)


        //INizialize
        animator = UIDynamicAnimator(referenceView: self.view!)

        //Add Gravity

        //animator?.addBehavior(gravity, sprite)


        var test = arc4random() % 90

        blueSquare.size = CGSize(width: 100, height: 100)
        blueSquare.position = CGPoint(x: CGFloat(X), y: 1000)
                blueSquare.zRotation = 34
        blueSquare.name = "bluecube"
        blueSquare.physicsBody = SKPhysicsBody(circleOfRadius: 20)
        blueSquare.physicsBody?.affectedByGravity = true
        blueSquare.physicsBody?.dynamic = false
        blueSquare.color = SKColor.blueColor()
       // BlueSquare.physicsBody?.velocity = CGVectorMake(0, 0)

        //BlueSquare.physicsBody?.applyImpulse(CGVectorMake(0, -90))
        self.addChild(blueSquare)

        let X2 = arc4random() % width
        redSquare.size = CGSize(width: 100, height: 100)
        redSquare.position = CGPoint(x: CGFloat(X2), y: 1000)
        redSquare.name = "redcube"
        redSquare.physicsBody = SKPhysicsBody(circleOfRadius: 20)
        redSquare.physicsBody?.affectedByGravity = true
        redSquare.physicsBody?.dynamic = true
        redSquare.hidden = false
        redSquare.physicsBody?.categoryBitMask = PhysicsCategory.RedSquare
        redSquare.physicsBody?.contactTestBitMask = PhysicsCategory.touchlocation

        redSquare.color = SKColor.redColor()

        self.addChild(redSquare)




        let timerAction1 = SKAction.waitForDuration(0.5)
        let timerAction2 = SKAction.runBlock(spawning1)
        let timerSequence = SKAction.sequence([timerAction1, timerAction2])
        runAction(SKAction.repeatActionForever(timerSequence))

    }

    func didBeginContact(contact: SKPhysicsContact) {
        var firstBody : SKPhysicsBody = contact.bodyA
        var secondBody : SKPhysicsBody = contact.bodyB

        print("didbegincontact")
        if ((firstBody.categoryBitMask == PhysicsCategory.RedSquare) && (secondBody.categoryBitMask == PhysicsCategory.touchlocation)) || ((firstBody.categoryBitMask == PhysicsCategory.touchlocation) && (secondBody.categoryBitMask == PhysicsCategory.RedSquare)) {
            collisionwithredsquare(firstBody.node as! SKSpriteNode)
            print("Done")

        }
    }


    func collisionwithredsquare(redsquare: SKSpriteNode) {
        print("Hello")
    }


    func spawning1() {


    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
       /* Called when a touch begins */

        for touch in touches {
            let location = touch.locationInNode(self)

            touchpoint.position = location

        }
    }

    func score () {
        scorenumber++
        print(scorenumber)
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
       if CGRectIntersectsRect(redSquare.frame, ground.frame) {
        redSquare.position = CGPoint(x: redSquare.position.x, y: redSquare.position.y + 10)
        }
    }
}

提前致谢,尼尔

最佳答案

你的碰撞类别是错误的。应该是这样,因为您正在处理 32 位整数。

  struct PhysicsCategory {
      static let RedSquare: UInt32 = 0x1 << 1
      static let touchlocation : UInt32 = 0x1 << 2
      static let BlueSquare : UInt32 = 0x1 << 3
  }

如果你使用你的方式,你必须这样写

  struct PhysicsCategory {
      static let RedSquare: UInt32 = 1
      static let touchlocation : UInt32 = 2
      static let BlueSquare : UInt32 = 4
      static let somethingElse : UInt32 = 8
  }

这更令人困惑,因为您不能只将最后一个数字递增 1。

比将您的碰撞代码更改为此。这样您就不必在 if 语句中检查两个主体。

    /// Did Begin Contact
func didBeginContact(contact: SKPhysicsContact) {
    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody

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

  if (firstBody.categoryBitMask == PhysicsCategory.RedSquare) && (secondBody.categoryBitMask == PhysicsCategory.touchlocation) {
        collisionwithredsquare(firstBody.node) // I aim pretty sure you dont need to cast as SKSpriteNod, because the body its already a SKNode.
        print("Done")

    }
  }

另外,在 touchLocaiton Sprite 上,您忘记给它一个物理体。

  touchpoint.pysicsBody = SKPhysicsBody(..) // FORGOT THIS LINE
  touchpoint.physicsBody?.categoryBitMask = PhysicsCategory.touchlocation
    touchpoint.physicsBody?.contactTestBitMask = PhysicsCategory.RedSquare
    touchpoint.physicsBody?.affectedByGravity = false

如果您已经获得要调用的联系方式,这现在应该可以工作了。让我知道进展如何。

关于ios - 没有在 Swift 中正确检测碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36307165/

相关文章:

ios - FIRApp.configure() 创建内存泄漏 IOS

json - 对成员 'dataTask(with:completionHandler:)' 错误的引用不明确

ios - ios 的 swift 中带有 uitableview 的侧边栏菜单

ios - 在显示之前将 ViewController 加载到 ContainerView 中,因此没有可见的过渡

swift - 随机生成节点

ios - Sprite 在暂停和取消暂停后移动两个位置

swift - Spritekit SKTexture(SKTexture 中的 : CGRect, 矩形)问题

ios - 创建一个每秒运行的计时器,在第二个?

ios - 从 UITableView 选定索引更新 detailDescriptionLabel 数据

ios - 覆盖 View 在 UINavigationBar 上不紧密