如何添加与多个精灵的碰撞

Posted

技术标签:

【中文标题】如何添加与多个精灵的碰撞【英文标题】:how to add collision with multiple sprites 【发布时间】:2021-11-26 01:47:22 【问题描述】:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
        guard let touch = touches.first else  return
        let location = touch.location(in: self)
        lastTouchPosition = location
    
        let bullet = SKSpriteNode(imageNamed: "bullet")
        bullet.name = "bullet"
        bullet.position = player.position
        bullet.physicsBody?.categoryBitMask = CollisionTypes.enemy.rawValue
        bullet.physicsBody?.contactTestBitMask = CollisionTypes.enemy.rawValue
        bullet.physicsBody?.collisionBitMask = CollisionTypes.enemy.rawValue
        
        bullet.size = CGSize(width: 40, height: 30)
        bullet.physicsBody = SKPhysicsBody(circleOfRadius: bullet.size.width / 2)
        addChild(bullet)
    

我用 SKPhysicsBody 为我的子弹添加了碰撞,它射击并与我的敌人相撞。然而,每次我触摸屏幕射击时,我的球员都会被击退,几乎就像它有后坐力一样。如果我确实从子弹中移除 SKPhysicsBody,一切正常,但我的子弹只会穿过我的敌人。

    player.physicsBody?.categoryBitMask = CollisionTypes.player.rawValue
    player.physicsBody?.contactTestBitMask = CollisionTypes.enemy.rawValue
    player.physicsBody?.collisionBitMask = CollisionTypes.enemy.rawValue
    player.physicsBody?.collisionBitMask &= ~CollisionTypes.bullet.rawValue 

     playerNode.physicsBody?.restitution = -1.0
     playerNode.physicsBody?.friction = 0.0
     playerNode.physicsBody?.angularDamping = 0.0
     playerNode.physicsBody?.linearDamping = 0.5

【问题讨论】:

这取决于你如何为每个角色分配物理类别。 您需要为玩家显示物理体的代码以及您的didBegin(contact:)。从你所说的来看,玩家似乎正在与子弹相撞。 【参考方案1】:

您需要显示玩家的物理体代码以及您的didBegin(contact:)。从您所说的情况来看,玩家似乎正在与子弹发生碰撞,除非您采取特定措施来阻止它,否则它会这样做。

子弹是根据玩家的位置创建的,因此他们试图占据相同的空间。如果您没有关闭玩家和子弹之间的碰撞,那么玩家将与子弹发生碰撞并被“推”开——正如您所说的“被击退”。子弹不受影响,因为您已将子弹的collisionBitMask 设置为仅作为敌人。

要关闭玩家和子弹之间的碰撞而不影响玩家可能碰撞它的任何其他东西,您可以使用:

player.physicsBody?.collisionBitMask &= ~CollisionTypes.bullet.rawValue  

编辑: (你是对的 - didBegin 不需要碰撞)

我认为在为子弹定义physicsBody 时有一个问题:

bullet.physicsBody?.categoryBitMask = CollisionTypes.enemy.rawValue
bullet.physicsBody?.contactTestBitMask = CollisionTypes.enemy.rawValue
bullet.physicsBody?.collisionBitMask = CollisionTypes.enemy.rawValue
bullet.size = CGSize(width: 40, height: 30)
bullet.physicsBody = SKPhysicsBody(circleOfRadius: bullet.size.width / 2)

对于子弹的physicsBody 的前3 个引用,您使用的是可选的(bullet.physicsBody?),它表示“如果physicsBody 不为空,则执行此操作...除非它将为空。您需要创建physicsBody的行(上面块的最后一行)是实际创建physicsBody的第一行。目前您的categoryBitMask,collisionBitMask和contactTestBitMask没有为子弹设置。虽然这应该使子弹“碰撞”与播放器一起弹跳。

您是否正在为玩家做类似的事情,因为听起来确实好像碰撞检测导致它从子弹上反弹。

这可能会有所帮助 - 如果您知道这些内容,我们深表歉意。 :How to Detect collision in Swift, Sprite kit

这是一个有碰撞的小示例项目:https://***.com/a/43605825/1430420

这两个答案都是几年前的,所以我希望它们仍然适用于最新版本的 ios、SpriteKit 和 Swift。

编辑2:

我也刚刚注意到这一点:

    bullet.physicsBody?.categoryBitMask = CollisionTypes.enemy.rawValue

您正在尝试将子弹归类为敌人。你是故意的吗?虽然由于还没有设置子弹的physicsBody,所以这行代码没有任何作用。

实际发生的是,当您创建子弹的实际物理体时,categoryBitMask 的默认设置为全 1。 (https://developer.apple.com/documentation/spritekit/skphysicsbody/1519869-categorybitmask) 意味着它会与一切发生碰撞。然后当你关闭玩家和子弹类别之间的碰撞时:

player.physicsBody?.collisionBitMask &= ~CollisionTypes.bullet.rawValue 

玩家和子弹仍然会发生碰撞,因为您已经关闭了玩家和physicsBody 之间的碰撞,只有子弹的类别,但子弹的physicsBody 有一个类别,即玩家的collisionBitMask 是:

11111111111111111111111111111101(假设敌人类别为2)

子弹的位掩码是:

11111111111111111111111111111111 因为你在创建physicsBody后没有改变它。

当你将子弹的physicsBody的定义移到bitMask设置之前,你就会出现玩家的collisionBitMask还在的情况:

11111111111111111111111111111101(假设敌人类别为2)

但子弹的碰撞位掩码现在是:

00000000000000000000000000000100(假设你的敌人类别是 4),因为你给子弹的物理体类别 BitMask 敌人的类别,他们仍然发生碰撞,因为位 2 在两个位掩码中都是 1。

【讨论】:

我尝试为播放器和子弹更改它,但不幸的是,它仍然不起作用。我也没有我的 didBegin(contact:) 代码,因为我现在只想让它发生碰撞,这对玩家有用。我是否需要 SKPhysicsBody 才能让我的子弹与敌人相撞 我也尝试将碰撞设置为零。没有任何效果。玩家和子弹仍然以某种方式相互碰撞 你是如何将冲突设置为零的?我还在我的答案中添加了一些可能有帮助的东西 - 请参阅编辑 是的 - 如果您只是测试碰撞,则不需要 didBegin(),您不需要设置 physicsWorld.contactDelegate = self 或将您的课程设为 SKPhysicsContactDelegate 好的,我会看看这些例子。我更新了顶部的代码,以显示我的播放器可能导致此碰撞问题的内容。 bullet.physicsBody?.collisionBitMask = 0;我就是这样设置的。碰撞为零,但设置 isDynamic = false 也无济于事。

以上是关于如何添加与多个精灵的碰撞的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 游戏的多个 CCTMXTiledMaps

如何检测精灵套件中的碰撞?

快速创建具有相同纹理的多个精灵(节点)

如何检测pygame中的碰撞?

动画精灵与碰撞检测

在节点中使用精灵套件问题进行游戏开发?