SpriteKit - 确定正方形碰撞的哪一面

5

我正在开发的应用程序中,有两个立方体发生碰撞。我按照标准方法进行检查。在我的 "didBeginContact" 方法中,应用程序会告诉我它们何时发生碰撞。

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

我知道碰撞发生的位置,但因为它是两个正方形,所以可能会在边缘的任何一点,包括角落。那么如何检查左/右/上/下的碰撞呢?

编辑:正确答案:这可能不是最简洁的方法,但它有效。希望将来有人能从中受益。

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;
        }
    }
}

添加了一些相关代码。这是我的代码,所以其中包含变量等内容,但您应该能够理解。

2个回答

4

我认为确定联系的哪一侧涉及(顶部,左侧,底部,右侧)的最佳方法是:

  • 计算中心十字留下的点,用于上,下,左和右侧(例如,如果您有一个正方形精灵..)

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)
  • 计算接触点与每个边缘点(上、左、右和下之间的距离

可以使用以下简单的函数完成此步骤:

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)))
}

接下来,计算出的最小距离涉及的点是最靠近contactPoint的侧面点。

这种方法的优点

  1. 您不需要绘制僵尸或幽灵节点和相关物理体
  2. 这种方法也适用于动态可变CGPath,不仅适用于已知的矩形边界
  3. 速度快,代码行数少,如果您添加其他几行代码,还可以确定对角线并使您的算法更加精确。

3
最简单的方法是在正方形的顶部、左侧、右侧和底部添加子sprite。将物理引擎体添加到这些sprite上,然后您可以确定碰撞发生的位置。我建议首先尝试这种方法,除非屏幕上有很多正方形。
如果屏幕上有大量的正方形并且您担心性能问题,则可以使用contact.contactPoint,并将该点转换为正方形坐标。根据正方形的中心点、正方形的旋转角度和该点,您应该能够确定正方形碰撞的位置。这需要一些数学计算……我担心当第一种方法可能是您真正需要的全部时,编写这种解决方案。

你的第一个方法非常有效,我不知道为什么我没想到。谢谢! - CMilby
1
如果这个回答对您有帮助,您介意将其标记为正确答案吗? - hamobi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接