我正在制作一个太空入侵者风格的游戏,并希望能够让敌人在爆炸前被击中三次。
我使用的教程只展示了如何让敌人在一次击中后爆炸。它使用名为didBegin(_ contact: SKPhysicsContact)
https://www.youtube.com/watch?v=F0kcw6eryJs&t=617s
现在,根据我的理解,这个函数评估每个联系实例,为两个实体分配两个不同的角色,然后决定如何处理每个实体。我假设有一个敌人接受三次命中,将使用包含其剩余生命值的变量。然后,对于每个接触实例,变量将减1,直到它为零,敌人被移除。
但是,这有一个很深的问题。由于didBegin(_ contact: SKPhysicsContact)
仅评估一个联系实例,因此它不了解其他先前的联系实例。从本质上讲,当一个敌人被击中时,无法知道敌人是否曾被击中,未被击中或被击中太多次。如果只有一个敌人,那么我可以使用一个变量来跟踪其健康状况。但事实并非如此,因为屏幕上同时存在多个敌人,并且每次进行接触时,都无法知道先前的击打是在这个敌人还是另一个敌人身上。
如果屏幕上有一个敌人,那很简单,因为每次接触都必须是那个敌人。但如果屏幕上有多个实体,则无法知道联系人适用于哪个敌人。
我认为这需要对敌人的每个实例进行某种识别,但我不确定如何做到这一点。对于那些阅读的人,我非常感谢你们的参与,如果你能提供帮助,我将非常感激。
答案 0 :(得分:0)
你是绝对正确的,你需要以自己的方式追踪你的敌人和他们的健康。可能有很多方法可以做到,但这是实现目标的一种方式:
使用健康的敌人字典。每个敌人都会被赋予某种身份以识别他们。健康可以表示为Int。这本字典也可用于轻松判断还有多少敌人。
var enemyHealth = [String:Int]()
节点有一个name属性,您可以将任何字符串值设置为。这就是您能够识别节点的方式。创建敌人时,您将创建一个id(例如生成一个随机数),将该节点的名称设置为id,并使用默认的健康值将敌人添加到enemyHealth
字典中。 / p>
let enemyNode = SKSpriteNode(color: UIColor.white, size: CGSize.zero)
let enemyId = "\(arc4random())"
enemyNode.name = enemyId
enemyHealth[enemyId] = 10
...
在didBegin(_ contact: SKPhysicsContact)
中,您可以使用函数的联系参数(contact.bodyA.node
或contact.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
词典中删除。
答案 1 :(得分:0)
无需保留单独的词典来跟踪精灵的状态
每个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中),它可以让你知道特定的子弹是否已经与入侵者联系。