【问题标题】:How to set up an ID system for enemies in Sprite Kit?如何在 Sprite Kit 中为敌人设置 ID 系统?
【发布时间】:2020-01-31 08:45:46
【问题描述】:

我正在为 iOS 制作一款 2d Space Shooter 风格的游戏,但在为游戏元素尤其是敌人创建 ID 系统时遇到了麻烦。

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

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

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

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

我知道我必须设置一个 ID 系统,以便在检测到联系后调用,我只是不知道该怎么做。

我尝试过设置字典和类结构(我知道你可以这样解决它,但我无法弄清楚)。

【问题讨论】:

  • 您可以继承SKNode 以添加诸如“健康”之类的属性。然后,当您获得联系时,您确定其中一个节点是否是您的敌人子类(使用as?is)并减少生命值。然后就可以判断敌人是否被消灭了。
  • @Paulw11 非常感谢您的回复。我有子类 SKNode 来添加健康,我只是不清楚如何使用(as?)或(is)来确定我的敌人是哪一个。您能否提供一个有关如何使用它的示例。如果这是非常基本的,我很抱歉,但我被卡住了,真的很想能够克服这个障碍。提前谢谢你摇滚! :)

标签: ios sprite-kit


【解决方案1】:

您不必在didBegin 中填写您的联系代码,没有什么可以阻止您在didFinisheUpdate 中填写:

以下是您可以执行的操作的示例:

var contactedNodes = [SKNode]()
func didBegin(_ contact: SKPhysicsContact) {
    func storeContact(nodeA:SKNode,nodeB:SKNode){
        nodeA.userData = nodeA.userData ?? [:]()
        nodeA.userData["nodesHit"] += [nodeB]
        contactedNodes.append(nodeA)
    }
    storeContact(contact.bodyA.node,contact.bodyB.node)
    storeContact(contact.bodyB.node,contact.bodyA.node)

} 
func didFinishUpdate(){
    for node in contactedNodes{
        guard let userData = node.userData, let nodesHit = userData["nodesHit"] else {continue}
        //do any logic here with nodes hit
    }
}

就ID而言,你也可以使用userData来分配一个userID,不用担心额外的类

【讨论】:

    【解决方案2】:

    可能最简单的方法是继承SKNode 并将其用于你的敌人。您可以将health 属性添加到您的EnemyNode 并将其初始化为合适的值。

    然后在didBegin(_ contact: SKPhysicsContact)你可以找到敌人,减少它的生命值并在适当的时候摧毁它。

    func didBegin(_ contact: SKPhysicsContact) {
        var enemy: EnemyNode? = nil
    
        if contact.bodyA.node is EnemyNode {
            enemy = contact.bodyA.node 
        } else if contact.bodyB.node is EnemyNode {
            enemy = contact.bodyB.node
        }
    
        if let enemy = enemy {
            enemy.health -= 1
            if enemy.health == 0 {
               //TODO:  explode enemy
            }
        }
    } 
    

    【讨论】:

    • 我知道这与建议的内容相反,但非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多