【问题标题】:Why is my collision registered when there is no collision?为什么没有碰撞时会记录我的碰撞?
【发布时间】:2014-08-15 16:02:34
【问题描述】:

请多多包涵,我在 XCode/IOS 上工作了一天,所以你可能需要解释一下……

我有一个碰撞方法:

func didBeginContact(contact: SKPhysicsContact!) {

    if (contact != nil && contact.bodyA != nil && contact.bodyB != nil)
    {
        var firstBody:SKPhysicsBody
        var seconBody:SKPhysicsBody

        if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
        {
            firstBody = contact.bodyA
            seconBody = contact.bodyB
        }
        else
        {
            firstBody = contact.bodyB
            seconBody = contact.bodyA
        }

        if (firstBody.categoryBitMask & torpedoCategory != 0 && seconBody.categoryBitMask & alienCategory != 0)
        {

            if firstBody.node != nil && seconBody.node != nil {
                torpedodidCollideWithAlien(firstBody.node as SKSpriteNode, alien: seconBody.node as SKSpriteNode)

            }
        }
    }
}

由此触发:

    var alien:SKSpriteNode = SKSpriteNode(imageNamed: "Alien")

    alien.physicsBody = SKPhysicsBody(texture: alien.texture, size: alien.size)
    alien.physicsBody.categoryBitMask = alienCategory
    alien.physicsBody.contactTestBitMask = torpedoCategory
    alien.physicsBody.collisionBitMask = 0
    alien.zPosition = -100000

我正在尝试使用 XCode 6 中可用的像素碰撞。问题是 didBeginContact 方法在没有碰撞时触发,并且一次碰撞会触发多次。

我是否错误地使用了物理系统?

这里是完整项目的链接:https://www.dropbox.com/s/1npctvb99vw2l7x/BubbleBurst.zip

掩码值:

    let alienCategory:UInt32 = 0x1 << 1    
    let torpedoCategory:UInt32 = 0x1 << 0

【问题讨论】:

  • alienCategorytorpedoCategory 的值是多少?我无法下载您的项目,因为 Dropbox 被公司的防火墙阻止。
  • @BrunoWerminghoff - 我在问题的底部添加了额外的细节。

标签: ios swift sprite-kit xcode6 skphysicsbody


【解决方案1】:

我知道这不是您真正的答案,但它可能会帮助您找出实际答案。

I'm trying to use the pixel collision available in XCode 6. The issue is that the didBeginContact method is triggered when there is no collision, and it is triggered multiple times for one collision.

碰撞和接触是不同的东西。使用contactTestBitMask 检测接触(你在做什么)和collisionBitMask 启用与这些接触相关的物理(碰撞本身)。在更实际的情况下,contactTestBitMask 应该用于使用您的代码处理某些事情,而 SpriteKit 使用collisionBitMask 来制作,例如,当一个对象碰到另一个对象时反弹。

如果您使用collisionBitMask,您可能会摆脱第二个问题(“[didBeginContact] 多次触发一次碰撞”)。

对于您的第一个问题(“没有碰撞时触发了didBeginContact [...]”),我会尝试更改您的alien.physicsBody。我会完全猜测这部分,但也许你的图像是 300x300,你希望你的外星人有 150x150 的像素大小。也许你的alien.physicsBody 比它看起来大,因此它的物理体在视觉表示之前接触到另一个对象的物理体。

【讨论】:

  • 外星人的精灵在边缘被修剪,而不是像球在代码中碰撞那样有 30px 的偏移。我读到在 XCode6 中使用带有纹理和大小的 SKPhysicsBody 允许基于像素的碰撞,其中精灵的大小在很大程度上并不重要,它可以利用精灵中的 alpha 值来检测要碰撞的像素在哪里。我想使用 swift/xcode6 中提供的每像素碰撞系统来检测我的代码中复杂形状上的碰撞。此外,碰撞/接触在 SK 中可能是不同的东西,但在我看来它们是一回事;-)
【解决方案2】:

在您设置 SKView 的 viewController 中,我建议您在解决此问题时将其打开。

skView.showsPhysics = true

至于多次接触,那是完全正常的。如果您告诉 SpriteKit 测试接触重叠的两个节点,它将读取为每次循环运行的接触 (didSimulatePhysics)。假设您想要一个鱼雷来摧毁一个外星人,一个或两个都需要从场景中移除以阻止再次读取接触(可选隐藏或移动)。或者例如,如果您希望它使用多个鱼雷来摧毁外星人,则需要在接触时移除/移动鱼雷。

正如 Bruno 所提到的,SpriteKit 中的碰撞意味着两个对象可以作为实体以相互影响的方式进行。玩家可能会撞到墙(无法穿过它),但玩家可能能够穿过怪物。

您的 didBeginContact 代码也可以简单得多。下面是一个测试玩家是否击中了其他三个物理体 contactBitMask 之一的示例。

func didBeginContact(contact: SKPhysicsContact) {
    var other:SKPhysicsBody = contact.bodyA.categoryBitMask == Contact.Player ? contact.bodyB : contact.bodyA

    if other.categoryBitMask == Contact.Scene {
        // Do stuff for player hitting scene edge
    } else if other.categoryBitMask == Contact.Object {
        // Do stuff for player hitting the hazards
    } else if other.categoryBitMask == Contact.Score {
       // Do stuff for player scoring points
    }
}

【讨论】:

    猜你喜欢
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    相关资源
    最近更新 更多