2016-08-02 67 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个月没有问题:)