SpriteKit - identify the side faced by the area

So, for the application I'm working on, I came across two cubes. I check this in a standard way. The application tells me when they come across in my "didBeginContact" method.

-(void)didBeginContact:(SKPhysicsContact *)contact { if (contact.bodyA.categoryBitMask == WALL_CATEGORY && contact.bodyB.categoryBitMask == CHARACTER_CATEGORY) { CGPoint point = contact.contactPoint; } } 

So, I know where the collision occurs, but since it is two squares, it can be at any point along the side, including the corners. So, how would I check if the collision is left / right / top / bottom?

Edit: correct answer: This may not be the cleanest way, but it works. Hope this helps someone in the future.

 m_lNode = [SKNode node]; m_lNode.position = CGPointMake(-(CHARACTER_SIZE / 2), 0); m_lNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(1, m_character.size.height)]; m_lNode.physicsBody.allowsRotation = NO; m_lNode.physicsBody.usesPreciseCollisionDetection = YES; m_lNode.physicsBody.categoryBitMask = CHARACTER_L_CATEGORY; m_rNode = [SKNode node]; m_rNode.position = CGPointMake((CHARACTER_SIZE / 2), 0); m_rNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(1, m_character.size.height)]; m_rNode.physicsBody.allowsRotation = NO; m_rNode.physicsBody.usesPreciseCollisionDetection = YES; m_rNode.physicsBody.categoryBitMask = CHARACTER_R_CATEGORY; m_tNode = [SKNode node]; m_tNode.position = CGPointMake(0, (CHARACTER_SIZE / 2)); m_tNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(m_character.size.width , 1)]; m_tNode.physicsBody.allowsRotation = NO; m_tNode.physicsBody.usesPreciseCollisionDetection = YES; m_tNode.physicsBody.categoryBitMask = CHARACTER_T_CATEGORY; m_bNode = [SKNode node]; m_bNode.position = CGPointMake(0, -(CHARACTER_SIZE / 2)); m_bNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(m_character.size.width, 1)]; m_bNode.physicsBody.allowsRotation = NO; m_bNode.physicsBody.usesPreciseCollisionDetection = YES; m_bNode.physicsBody.categoryBitMask = CHARACTER_B_CATEGORY; [m_character addChild:m_tNode]; [m_character addChild:m_bNode]; [m_character addChild:m_lNode]; [m_character addChild:m_rNode]; -(void)didBeginContact:(SKPhysicsContact *)contact { if (contact.bodyA.categoryBitMask == WALL_CATEGORY) { switch (contact.bodyB.categoryBitMask) { case CHARACTER_T_CATEGORY: NSLog(@"Top"); m_isHitTop = true; break; case CHARACTER_B_CATEGORY: NSLog(@"Bottom"); m_isHitBottom = true; break; case CHARACTER_L_CATEGORY: NSLog(@"Left"); m_isHitLeft = true; break; case CHARACTER_R_CATEGORY: NSLog(@"Right"); m_isHitRight = true; break; } } } 

Corresponding code added. This is my code, so there are variables among others, but you must understand this.

+5
source share
2 answers

I think the best way to determine which side is involved in your contact (top, left, bottom, right) is as follows:

  • calculate the points highlighted by the centering cross for the sides up, down, left and right (for example, if you have a sprite square ..)

enter image description here

 let halfWidth = self.frame.width/2 let halfHeight = self.frame.height/2 let down = CGPointMake(self.frame.origin.x+halfWidth,self.frame.origin.y) let up = CGPointMake(self.frame.origin.x+halfWidth,self.frame.origin.y+self.frame.size.height) let left = CGPointMake(self.frame.origin.x,self.frame.origin.y+halfHeight) let right = CGPointMake(self.frame.origin.x+self.frame.size.width,self.frame.origin.y+halfHeight) 
  • Calculate the distance between the contact and from each point ( up, left, right and down )

This step may be possible with this little function:

 func getDistance(p1:CGPoint,p2:CGPoint)->CGFloat { let xDist = (p2.x - p1.x) let yDist = (p2.y - p1.y) return CGFloat(sqrt((xDist * xDist) + (yDist * yDist))) } 

After that, the point involved in calculating the lowest distance is the lateral point closest to the contact point.

What are the advantages of this method :

  • You do not draw zombies or ghostly nodes and relative physical bodies.
  • This method also works inside dynamic dynamic mutable CGPath, and not just with knowing rectangular borders
  • Quickly, a few lines of code, and if you add another few lines, you can also determine the diagonals and refine your algorithm.
+4
source

The easiest way is to add child sprites at the top, left, right, bottom of your squares. Add physical bodies to them, and then you can tell where the collision occurs. I would recommend trying this method first if you have a lot of squares on the screen.

If you have a ton of squares on the screen and you are worried about performance. then maybe use contact.contactPoint and convert that point to square coordinates. given the center point of the square, the angle of rotation of the squares, and that point, you should be able to tell where the square collided. This will require some math .. and I was afraid to write such a solution, when the first may be all that you really need.

+3
source

Source: https://habr.com/ru/post/1210614/


All Articles