【问题标题】:Enemy Taking Multiple Damage - Swift, Xcode 8.2.1敌人受到多重伤害 - Swift,Xcode 8.2.1
【发布时间】:2018-11-15 18:18:50
【问题描述】:

我正在制作一款太空侵略者风格的游戏,并且想要制作一个敌人必须被击中三下才能爆炸。

我使用的教程只展示了如何让敌人一击就爆炸。它使用了一个名为didBegin(_ contact: SKPhysicsContact)的函数

https://www.youtube.com/watch?v=F0kcw6eryJs&t=617s

现在,据我了解,这个函数会评估每个接触实例,为两个身体分配两个不同的角色,然后决定如何处理每个身体。我假设让一个敌人受到三击,将使用一个包含他们剩余生命值的变量。然后,每次接触,变量都会减一,直到为零,敌人被移除。

然而,这里面有一个深层次的问题。由于didBegin(_ contact: SKPhysicsContact) 只评估一个联系实例,它不知道其他先前的联系实例。本质上,当一个敌人被击中时,没有办法知道敌人是以前被击中过、根本没有被击中过还是被击中了太多次。如果只有一个敌人,那么我可以使用一个变量来跟踪它的健康状况。然而,情况并非如此,因为屏幕上同时有多个敌人,并且每次接触时,都无法知道上一次击中的是这个敌人还是另一个敌人。

如果屏幕上有一个敌人,这很简单,因为每次接触都必须是那个敌人。但如果屏幕上有多个实体,则无法知道接触适用于哪个敌人。

我相信这需要对每个敌人实例进行某种识别,尽管我不确定如何做到这一点。对于那些阅读的人,我非常感谢您的光临,如果您能提供帮助,我将非常感激。

【问题讨论】:

    标签: swift sprite-kit game-physics


    【解决方案1】:

    没有必要保留单独的字典来跟踪精灵的状态

    每个SKNode都有userData,你可以用它追踪敌人的生活

    例子:

    let invader = SKSpriteNode(imageNamed:"invader")
    invader.userData = ["health":3]
    
    ...
    
    
    func didBeginContact(...)
    {
    ...
      //when a contact happens
        contact.body_.node.userData["health"] -= 1
    ...
    }
    

    现在请记住,1 颗子弹可以击中 1 个敌人两次。您不想在这里触发 2 次生命损失,因此您需要有一个临时变量(您也可以将其保存在 userData 中),让您知道特定子弹是否已经与入侵者接触。

    【讨论】:

    • 非常感谢您!我想知道,在func didBeginContact 中扣除变量健康的确切格式是什么?当您提到 body_ 时,您是指 bodyA 还是 bodyB,或者我应该同时测试两者,因为它说 SKPhysicsContact 没有成员“body”。此外,当尝试减去一个时,它会给出错误Binary operator '-=' cannot be applied to operands of type 'Any?' and 'Int'。这很令人困惑,因为似乎可以对类型 Int 进行操作。再次感谢您的帮助。
    • Body_ 是你的入侵者的任何身体。该类别会告诉您这一点。
    【解决方案2】:

    您说的完全正确,您不知何故需要自己追踪敌人及其健康状况。可能有很多方法可以做到这一点,但这里有一种方法可以实现您的目标:

    使用带有健康状况的敌人字典。每个敌人都会被赋予某种 id 来识别他们。健康可以表示为一个 Int。这本字典也可以用来轻松地判断周围还有多少敌人。

    var enemyHealth = [String:Int]()
    

    节点有一个 name 属性,你可以设置任何字符串值。这就是您能够识别节点的方式。创建敌人时,您将创建一个 id(例如生成一个随机数),将节点名称设置为 id 并将敌人添加到 enemyHealth 字典中,并使用默认健康值。

    let enemyNode = SKSpriteNode(color: UIColor.white, size: CGSize.zero)
    let enemyId = "\(arc4random())"
    enemyNode.name = enemyId
    enemyHealth[enemyId] = 10
    ...
    

    didBegin(_ contact: SKPhysicsContact) 中,您可以使用函数的contact 参数(contact.bodyA.nodecontact.bodyB.node)访问碰撞中涉及的节点。通过将节点名称与enemyHealth 中的键进行比较,您可以确定哪个碰撞体是敌人以及它的生命值。

    let enemy:SKSpriteNode
    
    if enemyHealth.keys.contains(contact.bodyA.node?.name ?? "") {
        enemy = contact.bodyA.node as! SKSpriteNode
    
    } else if enemyHealth.keys.contains(contact.bodyB.node?.name ?? "") {
        enemy = contact.bodyB.node as! SKSpriteNode
    } else {
        return  //none of the collision partners are an enemy
    }
    
    let health = enemyHealth[enemy.name!]!
    ...
    

    现在你可以对敌人为所欲为。当敌人被杀死/移除时,也将其从enemyHealth 字典中移除。

    【讨论】:

      猜你喜欢
      • 2016-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 2020-10-10
      相关资源
      最近更新 更多