Reputation: 395
I have an array of Bullets and Enemies objects. I want the game to check each element in the arrays to see whether there was a collision between the two or not. If there was any collision, then damage that enemy and delete the bullet. Right now every time a bullet hits an enemy it decreases the health of ALL the enemies in the array, thus killing them all at once. How can I make it so that it only decreases the health of the enemy which I'm shooting at?
//This function handles our collision detection
func didBegin(_ contact: SKPhysicsContact) {
//print("COLLISIONS!")
// If contact is with another object
if contact.bodyA.categoryBitMask == pickupCategory && contact.bodyB.categoryBitMask == playerCategory
{
displayText(text: "Picked up Pistol")
player.setHasPistol(gotPistol: true)
pistol.removeFromParent()
}
//Bullet hits an object
if contact.bodyA.categoryBitMask == objectCategory && contact.bodyB.categoryBitMask == bulletCategory
{
bulletCleanup(killNow: true)
//print("BULLET HAS HIT THE PIPE!")
}
//Do collisions between bullets and enemies...
for bullet in bulletList
{
for enemy in enemyList
{
//if the enemy was hit have them take damage.
if contact.bodyA.categoryBitMask == enemyCategory && contact.bodyB.categoryBitMask == bulletCategory
{
//deletes the bullet after hitting an object
bulletCleanup(killNow: true)
//apply damage
enemy.setHitPoints(setPoints: enemy.getHitPoints() - pistol.getDamage())
// print("BULLET HAS HIT THE enemy!!!!")
}
}
}
}
Upvotes: 1
Views: 684
Reputation: 8134
didBegin(contact:)
is called for a single collision between one specific object and another specific object. (actually between physics bodies...)
Your problem is occurring because you are iterating over every bullet and every enemy for a single collision and at each iteration you are testing if the collision was between a bullet and an enemy, which it was, so you are applying the damage to every enemy.
All you need to do is to extract the specific enemy from the SKPhysicsContact
object and apply damage to that particular enemy.
Also, I suspect you are missing some contacts because for your contact tests, you are not checking if the bodyA
and bodyB
physics bodies are reversed i.e.
if contact.bodyA.categoryBitMask == pickupCategory && contact.bodyB.categoryBitMask == playerCategory
bodyA
might be player
and bodyB
might be pickup
, so you need to test for this also.
Here is an alternative didBegincontact()
you might find helpful (It's Swift2, but that shouldn't be a big problem):
func didBeginContact(contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case pickupCategory | playerCategory
displayText(text: "Picked up Pistol")
player.setHasPistol(gotPistol: true)
let pistol = (contact.bodyA.categoryBitMask == pickupCategory) ? contact.bodyA.node! : contact.bodyB.node!
pistol.removeFromParent()
case objectCategory | bulletCategory
bulletCleanup(killNow: true)
//print("BULLET HAS HIT THE PIPE!")
case enemyCategory| bulletCategory
//deletes the bullet after hitting an object
bulletCleanup(killNow: true)
//apply damage
let enemy = (contact.bodyA.categoryBitMask == enemyCategory) ? contact.bodyA.node! : contact.bodyB.node!
enemy.setHitPoints(setPoints: enemy.getHitPoints() - pistol.getDamage())
default :
//Some other contact has occurred
print("Some other contact")
}
}
I'm not sure how your bulletCleanup()
function works - you don't appear to be sending it a specific bullet object so I don't know how it knows which bullet to process. The specific bullet involved in the contact can be obtained in didBegincContact:
as follows:
let bullet = (contact.bodyA.categoryBitMask == bulletCategory) ? contact.bodyA.node! : contact.bodyB.node!
which is a short form of saying "is nodeA
's categoryBitMask
a bulletCategory
? If it is, then set bullet
equal to nodeA
, otherwise set bullet
to nodeB
.
Note that if your categories are more complicated (i.e. objects can belong to multiple categories), this won't work as the simple AND tests (enemyCategory| bulletCategory
) won't match.
Upvotes: 2