【问题标题】:SpriteKit won't recognise contactSpriteKit 无法识别联系人
【发布时间】:2017-03-10 04:27:20
【问题描述】:

下面是我的代码,由于某种原因无法识别两个精灵之间的接触,在这种情况下,忍者和左墙或右墙。所以我的问题是我错过了什么?我添加了碰撞类别并相应地分配了它们

func didBegin(_ contact: SKPhysicsContact) {

    let nodeB = contact.bodyB.node!

    if nodeB.name == "RIGHT_WALL"  {

        print("right wall touched")
        RightWallTouched = true
        self.CurrentScore = self.CurrentScore + 1

    }
    if nodeB.name == "LEFT_WALL" {

        print("left wall touched")
        RightWallTouched = false
        self.CurrentScore = self.CurrentScore + 1

    }

    self.CurrentScoreLabel.text = "\(self.CurrentScore)"

    if nodeB.name == "SPIKE" {

        self.GameStarted = false
        if(CurrentScore > HighScore){
            defaults.set(CurrentScore, forKey: self.HighScoreStorageKey)
            defaults.synchronize()
            self.HighScoreLabel.text = "\(self.defaults.integer(forKey: self.HighScoreStorageKey))"
        }
        endGame()
    }
}




func CreateNinja(){

    let ninjaTexture = SKTexture(imageNamed: "ninja-right.png")
    ninjaTexture.filteringMode = .nearest
    self.ninja = SKSpriteNode(texture: ninjaTexture)
    self.ninja!.physicsBody = SKPhysicsBody(texture: ninjaTexture, size: ninja!.size)
    self.ninja?.name = "NINJA"
    self.ninja!.physicsBody?.isDynamic = false
    self.ninja!.physicsBody?.allowsRotation = false
    self.ninja!.physicsBody?.restitution = 0.6
    self.ninja!.physicsBody?.mass = 0.430 // m = 430g
    self.ninja!.position = CGPoint(x: self.frame.size.width / 2 , y: self.frame.size.height/5)
    self.ninja!.physicsBody?.categoryBitMask = ninjaCollisionCategory
    self.ninja!.physicsBody?.contactTestBitMask = 0
    self.ninja!.physicsBody?.collisionBitMask = wallCollisionCategory
    self.addChild(self.ninja!)
}


func CreateWall(){

    let topwall = SKSpriteNode()
    topwall.name = "TOP_WALL"
    topwall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.frame.size.width, height: 5))
    topwall.physicsBody?.categoryBitMask = wallCollisionCategory
    topwall.physicsBody?.isDynamic = false
    topwall.physicsBody?.restitution = 0.6
    topwall.position = CGPoint(x: self.frame.size.width / 2.0 , y: self.frame.size.height)
    topwall.physicsBody?.friction = 0
    topwall.zPosition = 4
    self.addChild(topwall)

    let leftwall = SKSpriteNode(color: UIColor.black, size: CGSize(width: 20, height: self.frame.size.height))
    leftwall.name = "LEFT_WALL"
    leftwall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 20, height: self.frame.size.height))
    leftwall.physicsBody?.categoryBitMask = wallCollisionCategory
    leftwall.physicsBody?.contactTestBitMask = 0
    leftwall.physicsBody?.isDynamic = false
    leftwall.position = CGPoint(x: 0 , y: self.frame.size.height / 2.0)
    leftwall.zPosition = 4
    leftwall.physicsBody?.restitution = 1.0
    leftwall.physicsBody?.friction = 0
    self.addChild(leftwall)

    let rightwall = SKSpriteNode(color: UIColor.black, size: CGSize(width: 20, height: self.frame.size.height))
    rightwall.name = "RIGHT_WALL"
    rightwall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 20, height: self.frame.size.height))
    rightwall.physicsBody?.categoryBitMask = wallCollisionCategory
    rightwall.physicsBody?.contactTestBitMask = 0
    rightwall.physicsBody?.isDynamic = false
    rightwall.physicsBody?.restitution = 1.0
    rightwall.physicsBody?.friction = 0
    rightwall.position = CGPoint(x: self.frame.size.width , y: self.frame.size.height / 2.0)
    rightwall.zPosition = 4
    self.addChild(rightwall)
}

【问题讨论】:

  • 如何知道节点 B 是墙?订单没有保证,所以据你所知,节点 A 是墙,self.ninja!.physicsBody?.contactTestBitMask = 0 表示 ninja 无法联系任何东西
  • 是的,你是对的,我已经用简单的 if 语句解决了问题。谢谢!
  • 但是现在当我与右墙接触时,它算作两点,但当它接触左墙时,它是一个点o.O
  • 因为你的身体可以在多个接触点上触摸它
  • 几种方法,这取决于你,你需要以某种方式告诉系统你已经完成了检查

标签: sprite-kit swift3 xcode8 2d-games


【解决方案1】:

执行碰撞功能的更常见方法是这样的

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
     }

     // Ninja hit wall or wall hit ninja
     if (firstBody.categoryBitMask == ninjaCollisionCategory) && (secondBody.categoryBitMask == wallCollisionCategory) {

         // Do something for all walls
         ...

         // you can also check the name for some specific wall e.g.
         if secondBody.node?.name == "RIGHT_WALL" {
               // hit right wall
         }
     }
}

您还需要在 didMoveToView 中设置委托

physicsWorld.contactDelegate = self

并且可能应该将你的忍者精灵物理体设置为动态

ninja?.physicsBody?.isDynamic = true // You can also remove this line as its set to true by default

最后,作为一个好的做法,尽量遵循 Swift 指南,你的函数和属性应该以小写字母而不是大写字母开头,例如

var currentScore = 0
func createNinja() { ... }

希望对你有帮助

【讨论】:

  • 如果您将“isDynamic”设置为 false 以避免重力但仍然能够检查两个类别何时发生碰撞,这将如何工作?
猜你喜欢
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多