SpriteKit: detect complete node overlap

懵懂的女人 提交于 2019-11-30 07:42:07
CGPoint locObj1 = [sprite1 locationInNode:self];
CGPoint locObj2 = [sprite2 locationInNode:self];

if([sprite1 containsPoint: locObj2]) return;
if([sprite2 containsPoint: locObj1]) return;

Add this to the beginning of didBeginContact and didEndContact. This checks to see if one of the nodes contains the other node. If it does, it does nothing which will alleviate your issue of didBeginContact and didEndContact being unessesarily called. I am not on my mac so you may need to play with the syntax a bit. Hope this sends you in the right direction.

man1

As meisenman suggested, it looks like the best way to do this is using the containsPoint method to determine true node overlap. The docs state that this "returns a Boolean value that indicates whether a point lies inside the node's bounding box", but in my experimentation it looks like this works for concave edge-based shapes as well.

So if I want to detect when two objects no longer overlap, it makes sense to do a containsPoint check within didEndContact – but it turns out didEndContact gets called when each edge is no longer intersected, even if another edge of the same shape still intersects the same object. For example, a ball exiting a rectangle through its corner will yield two didEndContact events. Therefore, it's necessary to keep an absolute count of contact events (the difference between begin and end), and only test for containment when this count is zero.

My solution, in Swift:

var _contactCount = 0

func didBeginContact(contact: SKPhysicsContact!) {
  if ((contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask) == (CATEGORY_ONE | CATEGORY_TWO)) {
    if (_contactCount == 0) {
      // Contact is actually beginning
    }
    _contactCount += 1
  }
}

func didEndContact(contact: SKPhysicsContact!) {
  if ((contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask) == (CATEGORY_ONE | CATEGORY_TWO)) {
    _contactCount -= 1
    let overlap = contact.bodyA.node.containsPoint(contact.bodyB.node.position) || contact.bodyB.node.containsPoint(contact.bodyA.node.position)
    if (!overlap && _contactCount == 0) {
      // Contact is actually ending
    }
  }
}

These are my thoughts on #meisenman example for swift 3. Instead of collision detection through masks, let's say we wanted to to know if an node is inside a node. With #meisenman, the location of the node is being used for each.

This following image is what we actually what I want done.

The code #meisenman uses does not require SKPhysics. Here is the code in Swift 3.0

let Object_1: CGPoint! = Sprite_Object_1.position
//this obtains the location of the sprite node, through CGPoint.
if Object_Sprite_2.contains(Object_1){
    print("Then it is true, object 2 is within the location of object 1")
}

The only limitations that I have found are that if the center of these nodes are not within the body of the desired node, then this if statement will not be true. This has not been tested by setting the node's body defination (mask).

What I like, is having the ability to use this if statement throughout different functions or overide fuctions, this is not limited to only 'did begin' or 'touches moved.'

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!