2016-08-02 66 views
0

我正在製作一個簡單的遊戲,其中物體從屏幕的頂部落下並落在屏幕底部(類似於俄羅斯方塊)的地面上,其中玩家在地面上避免和摧毀物體。我希望玩家在碰到左右兩側時能夠摧毀物體,並且我希望玩家在物體落到他身上時被殺死。我也希望玩家能夠在不破壞物體的情況下跳上物體。在SpriteKit中給定SpriteNode的每一邊創建物理實體

我想弄清楚正確的座標,以便爲我的對象的每一面做一個物理體。 (這裏是一些代碼,我正在同,試圖做到這一點):

 let topLeftPoint = CGPointMake(1, (objectSprite.size.height)) 
     let bottomLeftPoint = CGPointMake(1 , 1) 
     let topRightPoint = CGPointMake((objectSprite.size.width), (objectSprite.size.height)) 
     let bottomRightPoint = CGPointMake((objectSprite.size.width), 1) 


     self.topSideBody = SKPhysicsBody(edgeFromPoint: topLeftPoint, toPoint: topRightPoint) 
     self.topSideBody.categoryBitMask = ObstacleSide.topSide.rawValue 
     self.topSideBody.contactTestBitMask = BodyType.player.rawValue | BodyType.grassObject.rawValue 


     self.leftSideBody = SKPhysicsBody(edgeFromPoint: topLeftPoint, toPoint: bottomLeftPoint) 
     self.leftSideBody.categoryBitMask = ObstacleSide.leftSide.rawValue 
     self.leftSideBody.contactTestBitMask = BodyType.player.rawValue | BodyType.grassObject.rawValue 

     self.rightSideBody = SKPhysicsBody(edgeFromPoint: topRightPoint, toPoint: bottomRightPoint) 
     self.rightSideBody.categoryBitMask = ObstacleSide.rightSide.rawValue 
     self.rightSideBody.contactTestBitMask = BodyType.player.rawValue | BodyType.grassObject.rawValue 

     self.bottomSideBody = SKPhysicsBody(edgeFromPoint: bottomLeftPoint, toPoint: bottomRightPoint) 
     self.bottomSideBody.categoryBitMask = ObstacleSide.bottomSide.rawValue 
     self.bottomSideBody.contactTestBitMask = BodyType.player.rawValue | BodyType.grassObject.rawValue 

     physicsBody = SKPhysicsBody(bodies: [topSideBody, leftSideBody, rightSideBody, bottomSideBody]) 
     objectSprite.physicsBody = physicsBody 
     //objectSprite.physicsBody?.categoryBitMask = BodyType.grassObject.rawValue 
     objectSprite.physicsBody!.friction = 0.0 
     objectSprite.physicsBody!.dynamic = true 
     objectSprite.physicsBody!.affectedByGravity = true 

     objectSprite.physicsBody!.restitution = 0.0 
     objectSprite.physicsBody!.allowsRotation = false 

     self.zPosition = 102 

我主要是不確定的,我應該使用,或者什麼座標,如果有做這個簡單的方法。我也沒有任何問題摧毀障礙,並根據我爲障礙設置的一些布爾值來殺死玩家,我的主要問題是玩家能夠在不破壞物體的情況下在物體的頂部行走。

+0

如果你想對每個身體碰撞做出不同的反應,比如碰到bottomSideBody時死機,碰到topSideBody時碰撞,那麼你需要創建4單獨的SKNodes(您可以將它們與一個共同的父母捆綁在一起)。使用SKPhysicsBody(body :)接受給定物體碰撞區域的聯合,並將它們組合成一個單一的物體,您將無法以後區分「子物體」。 – cpimhoff

+0

此外,您的點值應固定在0. let topLeftPoint = CGPoint(x:0,y:self.size.height)... – cpimhoff

+0

@cpimoff所以我想出了正確的座標並創建了4個單獨的SKPhysicsBodys來組成物理機構爲我的對象/障礙。我現在遇到障礙物本身碰撞的問題(objectSprite.physicsBody = SKPhysicsBody(body:[topSideBody,leftSideBody,rightSideBody,bottomSideBody])構成了我的對象/障礙節點)。我試圖給我的objectSprite一個categoryBitMask來處理它的碰撞,但這似乎並不奏效。當我將各個位掩碼分配給兩側時,我似乎無法讓它們碰撞 –

回答

0

如果對象是正方形或長方形,則不需要超過1個物理體。這是你如何做的一般概述:

請注意,我複製了this question的大部分代碼。我建議你閱讀它,以更好地瞭解最新進展

您的didBegin(_ contact:SKPhysicsContact)函數。

獲取對象節點和collisionPoint(讓我們假設對象是contact.bodyB.node),並把它傳遞給下面的功能:

let block = contact.bodyB.node as! SKSpriteNode 
let contactPoint = contact.contactPoint 


func handleCollision(block:SKSpriteNode, contactPoint:CGPoint){ 
     // find the corners and convert thoes points into the scene coordinate space 
     let topLeft = convert(CGPoint(x: -block.size.width/2, y: block.size.height/2), from: block) 
     let bottomLeft = convert(CGPoint(x: -block.size.width/2, y: -block.size.width/2), from: block) 
     let topRight = convert(CGPoint(x: block.size.width/2, y: block.size.height/2), from: block) 
     let bottomRight = convert(CGPoint(x: block.size.width/2, y: -block.size.width/2), from: block) 

     // Then we put these "referencePoints" into an array for easy acces. 
     // Note that we go in a clockwise direction from the top left 

     let referencePoints = [topLeft,topRight,bottomRight,bottomLeft] 

     // ***Find the closest corner relative to the contactPoint.*** 

     // Varible to store the closetCorner 
     var closestCorner = referencePoints[0] 

     //We set the prevDistance to something very large. 
     var prevDistance:CGFloat = 10000000 

     for corner in referencePoints{ 

      // We check the distance from the contactPoint to each corner. 
      // If the distance is smaler then the last checked corner we update the closestCorner varible and also the prevDistance. 
      let distance = hypot(corner.x - contactPoint.x, corner.y - contactPoint.y) 
      if distance < prevDistance{ 
       prevDistance = distance 
       closestCorner = corner 
      } 

     } 

     // Now lets find the NextCorner and prevCorner relative to the closestCorner. 
     var nextCorner:CGPoint 
     var prevCorner:CGPoint 
     let index = referencePoints.index(of: closestCorner) 

     if index == 3{ 
      nextCorner = referencePoints[0] 
     } 
     else{ 
      nextCorner = referencePoints[index! + 1] 
     } 

     if index == 0{ 

      prevCorner = referencePoints[3] 

     } 
     else{ 
      prevCorner = referencePoints[index! - 1] 
     } 



     // Distance from closestCorner to nextCorner. 
     let distToNextCorner = hypot(closestCorner.x - nextCorner.x, closestCorner.y - nextCorner.y) 
     // Distance from contactPoint to nextCorner 
     let distFromContactPoint = hypot(contactPoint.x - nextCorner.x, contactPoint.y - nextCorner.y) 



     let firstSurfacePoint = closestCorner 
     var secondSurfacePoint:CGPoint 

     if distToNextCorner > distFromContactPoint{ 

      secondSurfacePoint = nextCorner 

     } 
     else{ 
      secondSurfacePoint = prevCorner 

     } 


     if firstSurfacePoint == topLeft || firstSurfacePoint == topRight && 
      secondSurfacePoint == topLeft || secondSurfacePoint == topRight { 

      // collision happend on the top side. Do something here to handle that 

     } 

     if firstSurfacePoint == topRight || firstSurfacePoint == bottomRight && 
      secondSurfacePoint == topRight || secondSurfacePoint == bottomRight { 

      // collision happend on the right side. Do something here to handle that 

     } 

     if firstSurfacePoint == bottomLeft || firstSurfacePoint == bottomRight && 
      secondSurfacePoint == bottomLeft || secondSurfacePoint == bottomRight { 

      // collision happend on the underside. Do something here to handle that 

     } 

     if firstSurfacePoint == topLeft || firstSurfacePoint == bottomLeft && 
      secondSurfacePoint == topLeft || secondSurfacePoint == bottomLeft { 

      // collision happend on the left side. Do something here to handle that 

     } 

    } 

這個答案可能是一點點馬虎,但如果有人問我可以改進它。因爲這個問題已經11個月沒有問題:)

相關問題